Страницы

Поиск по вопросам

среда, 25 декабря 2019 г.

Русские буквы в имени файла. TZipFile

#delphi #archive #delphi_xe8


Хочу разархивировать файл(*.zip). В нем содержатся файлы имена которых на русском.
Вот такая конструкция

procedure TWorkThread.ExctractZip(aArchFile: string; aPath: string);
var
  zZip: TZipFile;
begin
  zZip := TZipFile.Create;
  try
    zZip.ExtractZipFile(aArchFile, aPath);
  finally
    FreeAndNil(zZip);
  end;
end;


В итоге после разархивации имена этих файлов превращаются в кракозябру Çéè«¡Γα«½∞
αÑßΓ«αá¡δ.pdf

Как это побороть?
    


Ответы

Ответ 1



К сожалению, формат ZIP не слишком строго стандартизирован (к примеру, Unicode был официально стандартизирован в только в 2007 году - в спецификации PKWARE 6.3.2). Проблема даже не только в стандарте, сколько в бесчисленном количестве программ, которые сохраняют имена как им вздумается - что, в общем-то, не удивительно при такой спецификации. В частности, существует несколько вариантов хранения имён файлов с символами, выходящими за рамки ASCII: ANSI OEM CP437 (DOS Latin US) UTF-8 UTF-8 с флагом Дополнительное (extra) поле $7075 - стандарт PKWARE/Info-ZIP Дополнительное (extra) поле - я забыл числовой код, от другой программы Ужасная мешанина. Что хуже всего - часто нет никакого способа определить метод хранения имён, кроме ручного указания человеком (первые четыре способа из списка выше программно неразличимы). Поиграйтесь с флагом UTF8Support: если поможет - хорошо, если нет - надо или искать другой распаковщик, или другой упаковщик.

Ответ 2



Нужно изменить стандартный модуль zip.pas. Проверено на Delphi 10.2. function TZipFile.TBytesToString(B: TBytes): string; var E: TEncoding; begin if CyrillicSupport then //условие, нужна ли поддержка кириллицы, можно убрать E := TEncoding.GetEncoding(866) else if FUTF8Support then E := TEncoding.GetEncoding(65001) else E := TEncoding.GetEncoding(437); try Result := E.GetString(B); finally E.Free; end; end; function TZipFile.StringToTBytes(S: string): TBytes; var E: TEncoding; begin if CyrillicSupport then //условие, нужна ли поддержка кириллицы, можно убрать E := TEncoding.GetEncoding(866) else if FUTF8Support then E := TEncoding.GetEncoding(65001) else E := TEncoding.GetEncoding(437); try Result := E.GetBytes(S); finally E.Free; end; end;

Ответ 3



Я не специалист по дельфи, но вы можете попробовать стандартные decode-encode с разными кодировками. Составляете заранее словарик из русских букв и в каждой попытке определить кодировку побуквенно прогоняете полученное название через словарик. Как только нашли совпадение - вуаля. Это если проблемы с названием. Также, например, в питоне есть библиотека chardet, которая определяет кодировку самого файла, а не его названия.

Комментариев нет:

Отправить комментарий