Autor Téma: TZipFile a kódování  (Přečteno 427 krát)

Offline soko.ban

  • Nováček
  • *
  • Příspěvků: 10
  • Karma: 2
    • Verze Delphi: 10.4.1
TZipFile a kódování
« kdy: 23-10-2020, 17:26:18 »
Prosím o radu, nějak se nemůžu vyhrabat z následujícího problému.

Mám zip, který obsahuje názvy souborů s diakritikou a nejsem schopný ho pomocí TZipFile rozbalit se správnou češtinou.

Zip je vytvořen pomocí knihovny ZipForge. Nicméně úplně stejně se chová i zip vytvořený pomocí Total Commanderu v defaultním nastavení. Pokud zdrojový archiv vytvořím pomocí TZipFile, tak je to OK.

V Total Commanderu vytvořím zip se souborem Příliš žluťoučký kůň úpěl ďábelské ódy.txt a když ho rozbalím pomocí class procedure TZipFile.ExtractZipFile tak dostanu P²íliτ ºlu£ouƒk∞ kàσ úp╪l ╘ábelské ódy.txt. Stejná hámotina je i ve FileName v následujícím kódu.

Zkoušel jsme i různě cvičit s TZipFile.Encoding a různé pokusy s TEncoding.Default.GetString(LZip.FileInfo.FileName), ale bez výsledku.
Total Commander i 7Zip ty archivy samozřejmě zobrazí i rozbalí správně.

Co tam dělám blbě? Díky za každé popostrčení.

Zip na zkoušku je zde: https://1drv.ms/u/s!AphXA0AeJWXwhN4qVpmc6_d8bBd0Eg?e=Mb2zPV

Kód: Delphi [Vybrat]
  1.   var LZip := TZipFile.Create;
  2.   if LZip.IsValid(AFileName) then
  3.   begin
  4.     LZip.Open(AFileName, zmReadWrite);
  5.     for var i := 0 to LZip.FileCount - 1 do
  6.     begin
  7.       AddLog(i.ToString   ': '   LZip.FileName[i]); // P²íliτ ºlu£ouƒk∞ kàσ úp╪l ╘ábelské ódy.
  8.     end;
  9.     LZip.Close;
  10.   end;
  11.   LZip.Free;
  12.  

Offline JaroB

  • Guru
  • *****
  • Příspěvků: 1032
  • Karma: 29
    • Verze Delphi: XE8, Seattle
Re:TZipFile a kódování
« Odpověď #1 kdy: 23-10-2020, 19:45:56 »
Excellent
Rated 1 time
Tohle by mělo zabrat

Kód: Delphi [Vybrat]
  1.   function TBytesToString(B: TBytes): AnsiString;
  2.   var
  3.     E: TEncoding;
  4.   begin
  5.       E := TEncoding.GetEncoding(852);
  6.     try
  7.       Result := E.GetString(B);
  8.     finally
  9.       E.Free;
  10.     end;
  11.   end;
  12.  
  13. //----------------------------
  14.       LZip := TZipFile.Create;
  15.       if LZip.IsValid(AFileName) then
  16.       begin
  17.         LZip.Open(AFileName, zmReadWrite);
  18.         for i := 0 to LZip.FileCount - 1 do
  19.         begin
  20.           //CP852
  21.           s := string(TBytesToString(LZip.FileInfo[i].FileName));
  22.           showmessage(s);
  23.           //AddLog(i.ToString,   ': ',   LZip.FileName[i]); // P²íliτ ºlu£ouƒk∞ kàσ úp╪l ╘ábelské ódy.
  24.         end;
  25.         LZip.Close;
  26.       end;
  27.       LZip.Free;
  28.  

Offline soko.ban

  • Nováček
  • *
  • Příspěvků: 10
  • Karma: 2
    • Verze Delphi: 10.4.1
Re:TZipFile a kódování
« Odpověď #2 kdy: 23-10-2020, 20:54:09 »
3× hurá, děkuji velmi. Zkoušel jsem kdejakou codepage, ale tuhle samozřejmě ne.

Experimentálně jsem vyzkoušel, že stačí po otevření zipu nastavit tohle kódování celému objektu (a na koci uvolnit). Pak je správné kódování rovnou i ve FileName[] a není třeba přistupovat na FileInfo[].FileName. Je tam správně i pro zipy vytvořené v ZipForge/Total Commander i pro vytvořené pomocí TZipFile. 

Kód: Delphi [Vybrat]
  1. LZip.Encoding := TEncoding.GetEncoding(852);


Přiznávám, že moc nechápu jak to funguje. A to jsem se snažil někde načíst nějakou teorii. Výchozí kódování po OpenFile je všech případech 437 - OEM - Spojené státy.
Jsem trochu na vážkách, zda pokračovat v náhradě ZipForge za ZipFile v našem projektu. Rád byc, ale děsím se toho, na co ještě narazím.

Offline starous

  • Mladík
  • **
  • Příspěvků: 94
  • Karma: 2
    • Verze Delphi: Delphi 7, Delphi 10.4
Re:TZipFile a kódování
« Odpověď #3 kdy: 23-10-2020, 21:26:15 »
Neuvažoval jsi o knihovně Abbrevia? Použití je jednoduchý, není potřebná žádná externí knihovna a už nějakou dobu je součástí GetIt. Knihovna používá klasický string, takže s češtinou by být problém neměl (ale nezkoušel jsem, nepoužívám diakritiku).

Offline soko.ban

  • Nováček
  • *
  • Příspěvků: 10
  • Karma: 2
    • Verze Delphi: 10.4.1
Re:TZipFile a kódování
« Odpověď #4 kdy: 26-10-2020, 08:20:33 »
Abbrevia neznám.
Cílem bylo vyhodit externí placenou komponentu, když už to je zadara v RTL.

Offline starous

  • Mladík
  • **
  • Příspěvků: 94
  • Karma: 2
    • Verze Delphi: Delphi 7, Delphi 10.4
Re:TZipFile a kódování
« Odpověď #5 kdy: 26-10-2020, 08:53:07 »
https://github.com/TurboPack/Abbrevia

Je to součástí balíku knihoven Turbo Pack, kam patří i SynEdit, VirtualTreeView a další. Podle popisku máš nejnovější verzi Delphi, takže si to snadno stáhneš přes GetIt.


Offline soko.ban

  • Nováček
  • *
  • Příspěvků: 10
  • Karma: 2
    • Verze Delphi: 10.4.1
Re:TZipFile a kódování
« Odpověď #6 kdy: 26-10-2020, 11:03:44 »
JJ, našel jsem si to a nainstaloval. Je to něco podobnýho jako ZipForge, jen to je zadara. Cílem bylo zbavit se komponenty třetí strany. Takže to není úplně řešení našeho problému. ZipForge funguje, máme to koupený. S každou verzí Delphi stačí doplnit konstanty do inc souboru.

TZipFile zas neumí pracovat s zaheslovanými archivy. Resp. má na to rozhraní, ale sám to neumí. Přijde mi to od nich jako takový polovičatý řešení. Asi to nechám chvíli odležet.