错误的字符集文件名后解压
我有以下问题:我通过提取一个SSZipArchive zip文件(在斯威夫特的应用程序),并有与“无效”字的某些文件名。
我认为原因是我压缩了Windows下的文件,所以名称现在用ANSI编码。错误的字符集文件名后解压
有没有办法在解压缩过程中所有的“损坏”文件夹和文件名转换?
或更高版本?如果我必须迭代文件夹树并重命名文件,这将是没有问题的。
但我不知道如何找出哪些名称是在ANSI中设置的,我也不知道如何更正字符集。
可能在最新的SSZipArchive(目前2.1.1)中修复。我已经以类似于下面的代码的方式实现了对非Unicode文件名的支持,所以如果您愿意,您可以重复使用它来自己处理文件名。
OK,这是在Objective-C,但由于SSZipArchive具有自身修复已经,您应该不再需要它。否则,要么创建一个桥接头来包含Objective-C代码到你的swift应用中,要么将它转换成Swift(应该很容易)。
@implementation NSString (SSZipArchive)
+ (NSString *)filenameStringWithCString:(const char *)filename size:(uint16_t)size_filename
{
// unicode conversion attempt
NSString *strPath = @(filename);
if (strPath) {
return strPath;
}
// if filename is non-unicode, detect and transform Encoding
NSData *data = [NSData dataWithBytes:(const void *)filename length:sizeof(unsigned char) * size_filename];
// supported encodings are in [NSString availableStringEncodings]
[NSString stringEncodingForData:data encodingOptions:nil convertedString:&strPath usedLossyConversion:nil];
if (strPath) {
return strPath;
}
// if filename encoding is non-detected, we default to something based on data
// note: hexString is more readable than base64RFC4648 for debugging unknown encodings
strPath = [data hexString];
return strPath;
}
@end
@implementation NSData (SSZipArchive)
// initWithBytesNoCopy from NSProgrammer, Jan 25 '12: https://*.com/a/9009321/1033581
// hexChars from Peter, Aug 19 '14: https://*.com/a/25378464/1033581
// not implemented as too lengthy: a potential mapping improvement from Moose, Nov 3 '15: https://*.com/a/33501154/1033581
- (NSString *)hexString
{
const char *hexChars = "ABCDEF";
NSUInteger length = self.length;
const unsigned char *bytes = self.bytes;
char *chars = malloc(length * 2);
// TODO: check for NULL
char *s = chars;
NSUInteger i = length;
while (i--) {
*s++ = hexChars[*bytes >> 4];
*s++ = hexChars[*bytes & 0xF];
bytes++;
}
NSString *str = [[NSString alloc] initWithBytesNoCopy:chars
length:length * 2
encoding:NSASCIIStringEncoding
freeWhenDone:YES];
return str;
}
@end
的official spec说,路径应在代码页437 MS-DOS拉丁美或UTF-8(如果通用字段的第11位被置位)被任一编码:
d 0.1 ZIP格式历来支持只有原来的IBM PC 字符编码集,通常被称为IBM代码页437 此限制存储的文件名字符,只有那些值的 原始MS-DOS的范围内,并且不以其他字符编码或语言正确支持文件 。为解决此限制,本规范将支持以下更改。
D.2如果通用11位没有设置,文件名和注释 应符合原ZIP字符编码。如果一般 目的位11被设置为,文件名和注释必须支持的 Unicode标准,版本4.1.0或使用由UTF-8存储规范中定义的字符 编码形式越大。 Unicode标准由Unicode联盟 (www.unicode.org)发布。存储在ZIP文件中的UTF-8编码数据为 ,预期不包含字节顺序标记(BOM)。
我最近发布了名为ZIPFoundation ZIP文件格式的斯威夫特开源实现。它符合标准,应该能够检测Windows路径名并正确解码它们。
请提供样本zip并在github跟踪器上报告 –