2017-02-13 3 views
1

У меня есть следующая проблема: я извлек zip-файл через SSZipArchive (в приложении Swift), и есть некоторые имена файлов с «недопустимыми» символами.
Я думаю, причина в том, что я застегнул файлы под Windows и поэтому имена теперь закодированы в ANSI.Неверная кодировка имен файлов после unzip

Есть ли способ конвертировать все «поврежденные» папки и имена файлов во время процесса распаковки?
Или позже? Было бы непросто, если бы мне пришлось перебирать дерево папок и переименовывать файлы.
Но я не знаю, как узнать, какие имена установлены в ANSI, и я также не знаю, как исправить кодировку.

+0

предоставьте пример zip и сообщите об этом на github tracker –

ответ

0

Возможно, исправлено в последнем SSZipArchive (в настоящее время 2.1.1). Я реализовал поддержку имен файлов, отличных от Unicode, таким же образом, как и код ниже, поэтому вы можете повторно использовать его для обработки своих имен файлов, если хотите.

ОК, это в Objective-C, но поскольку SSZipArchive уже имеет исправление, вам больше не нужно. В противном случае либо создайте заголовок заголовка, чтобы включить код цели-кода в ваше быстрое приложение, либо преобразуйте его в 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://stackoverflow.com/a/9009321/1033581 
// hexChars from Peter, Aug 19 '14: https://stackoverflow.com/a/25378464/1033581 
// not implemented as too lengthy: a potential mapping improvement from Moose, Nov 3 '15: https://stackoverflow.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 
0

official spec говорит о том, что путь должен быть либо закодированы в кодовой странице 437 MS-DOS Латинской США или UTF-8 (если бит 11 поля общего назначения установлен):

D .1 Формат ZIP исторически поддерживал только оригинальный набор символов IBM PC , обычно называемый IBM Code Page 437. Это ограничивает хранение имен имен файлов только теми, что находятся в пределах диапазона значений MS-DOS 10, и не имеет значения правильно поддерживать файл имена в других кодировках символов или языках , Чтобы устранить это ограничение , эта спецификация будет поддерживать следующее изменение.

D.2 Если бит 11 общего назначения не установлен, имя файла и комментарий должны соответствовать оригинальной кодировке символов ZIP. Если задан общий бит, имя файла и комментарий должны поддерживать стандарт Unicode , версия 4.1.0 или выше, используя форму кодирования символов , определенную спецификацией хранения UTF-8. Стандарт Unicode опубликован Консорциумом Unicode (www.unicode.org). Кодированные данные UTF-8, хранящиеся в ZIP-файлах, равны , которые, как ожидается, не включают в себя знак порядка байтов (BOM).

Недавно я выпустил реализацию Swift с открытым исходным кодом формата ZIP-файла под названием ZIPFoundation. Он соответствует стандарту и должен иметь возможность определять имена путей Windows и правильно декодировать их.

Смежные вопросы