Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Programmieren allgemein (https://www.delphipraxis.net/40-programmieren-allgemein/)
-   -   Decompress einer gz-Datei mit NULL-Zeichen (https://www.delphipraxis.net/201231-decompress-einer-gz-datei-mit-null-zeichen.html)

philipp.hofmann 3. Jul 2019 15:16

Decompress einer gz-Datei mit NULL-Zeichen
 
Hi,

bisher decompresse ich gz-Dateien mit folgendem Code:

Delphi-Quellcode:
uses System.Zlib;

class function TStringUtils.gzUnzip(filename:String):TStringList;
var
   LInput:TFileStream;
   LUnZip:TZDecompressionStream;
begin
   Result:=TStringList.Create(true);
   LInput:=TFileStream.Create(filename,fmOpenRead + fmShareDenyNone);
   LUnZip:=TZDecompressionStream.Create(LInput,15+32);
   Result.LoadFromStream(LUnzip);
   LUnZip.Free;
   LInput.Free;
end;
Jetzt funktioniert dies leider nicht mit gz-Dateien, wo ein NULL-Zeichen enthalten ist. Dort enthält das Result dann nur den File-Inhalt bis zum NULL-Zeichen.
Wenn ich den Umweg über eine Datei gehe, welche ich dann in einem zweiten Schritt einlese, geht es zwar, ist aber inperformant, das mache ich eigentlich nur das riesen gz-Files:
Delphi-Quellcode:
class procedure TStringUtils.gzUnzipToFile(readFile,writeFile:String);
var
   LInput,LOutput:TFileStream;
   LUnZip:TZDecompressionStream;
begin
   LOutput:=TFileStream.Create(writeFile,fmCreate);
   LInput:=TFileStream.Create(readFile,fmOpenRead+fmShareDenyNone);
   LUnZip:=TZDecompressionStream.Create(LInput,15+32);
   LOutput.CopyFrom(LUnZip,0);
   LUnZip.Free;
   LInput.Free;
   LOutput.Free();
end;
Wie bekomme ich es hin, dass ich ohne den Umweg über eine Datei das gz-File komplett in meine TStringList bekomme?


Grüße, Philipp

DieDolly 3. Jul 2019 15:27

AW: Decompress einer gz-Datei mit NULL-Zeichen
 
Guck dir mal
Delphi-Quellcode:
TStrings.LoadFromStream
an.

philipp.hofmann 3. Jul 2019 18:43

AW: Decompress einer gz-Datei mit NULL-Zeichen
 
Ich verstehe die Aussage nicht so ganz: Soll ich mir TStrings.LoadFromStream anschauen, weil es eine Alternative ist (dann kann ich dies sein lassen, weil TStringList ist die Implementierung von TStrings) oder weil ich mir anschauen soll, was in dieser Implementierung schief läuft?

DieDolly 3. Jul 2019 21:05

AW: Decompress einer gz-Datei mit NULL-Zeichen
 
Ich habs jetzt nicht getestet aber mit DeineStringList.LoadFromStream() kannst du deinen Stream in deine StringList laden.
Zitat:

Wie bekomme ich es hin, dass ich ohne den Umweg über eine Datei das gz-File komplett in meine TStringList bekomme?

philipp.hofmann 3. Jul 2019 21:35

AW: Decompress einer gz-Datei mit NULL-Zeichen
 
Liste der Anhänge anzeigen (Anzahl: 1)
Ja, das Problem ist ja, wenn in dem gz-File (Beispiel im ZIP-Anhang) ein NUL-Zeichen enthalten ist, dann liest er nur bis zu NUL und nicht weiter.
Ich habe ein kleines Demoprojekt mit Beispiel gz-Datei hochgeladen, was das Problem verdeutlicht.
Die obere TMemo wird aus einer TStringList befüllt und dort steht nur der Header meiner gz-Datei.
Aber die untere TMemo wird direkt befüllt und dort steht alles, d.h. hier habe ich schon einen Hinweis auf eine Lösung, weil es in TMemo.Lines funktioniert, warum auch immer, ist aber schrecklich langsam bei großen Dateien. Aber da habe ich schon mal einen Ansatzpunkt, da TMemo.Lines eigentlich auch wieder TStrings ist.

DieDolly 3. Jul 2019 21:59

AW: Decompress einer gz-Datei mit NULL-Zeichen
 
Schon TBytesStream statt TFileStream getestet?

peterbelow 4. Jul 2019 11:01

AW: Decompress einer gz-Datei mit NULL-Zeichen
 
Zitat:

Zitat von philipp.hofmann (Beitrag 1435919)
Hi,

bisher decompresse ich gz-Dateien mit folgendem Code:

Delphi-Quellcode:
uses System.Zlib;

class function TStringUtils.gzUnzip(filename:String):TStringList;
var
   LInput:TFileStream;
   LUnZip:TZDecompressionStream;
begin
   Result:=TStringList.Create(true);
   LInput:=TFileStream.Create(filename,fmOpenRead + fmShareDenyNone);
   LUnZip:=TZDecompressionStream.Create(LInput,15+32);
   Result.LoadFromStream(LUnzip);
   LUnZip.Free;
   LInput.Free;
end;
Jetzt funktioniert dies leider nicht mit gz-Dateien, wo ein NULL-Zeichen enthalten ist. Dort enthält das Result dann nur den File-Inhalt bis zum NULL-Zeichen.
Wenn ich den Umweg über eine Datei gehe, welche ich dann in einem zweiten Schritt einlese, geht es zwar, ist aber inperformant, das mache ich eigentlich nur das riesen gz-Files:
Delphi-Quellcode:
class procedure TStringUtils.gzUnzipToFile(readFile,writeFile:String);
var
   LInput,LOutput:TFileStream;
   LUnZip:TZDecompressionStream;
begin
   LOutput:=TFileStream.Create(writeFile,fmCreate);
   LInput:=TFileStream.Create(readFile,fmOpenRead+fmShareDenyNone);
   LUnZip:=TZDecompressionStream.Create(LInput,15+32);
   LOutput.CopyFrom(LUnZip,0);
   LUnZip.Free;
   LInput.Free;
   LOutput.Free();
end;
Wie bekomme ich es hin, dass ich ohne den Umweg über eine Datei das gz-File komplett in meine TStringList bekomme?


Grüße, Philipp

Garnicht, macht auch keinerlei Sinn, da #0 innerhalb eines Strings eigentlich kein erlaubtes Zeichen ist. Mißbrauchst Du da einen String um binäre Daten zu speichern?

Außerdem: trau der Anzeige des stringlist-Inhalts im Debugger (oder in einem Control) nicht! #0 ist ein string-Terminator für Windows, selbst wenn die stringist deine #0s übernommen hat wird der Text nur bis zum ersten #0 angezeigt.

Außerdem: Welches Text-Encoding verwendete die gZippte Datei?

Redeemer 4. Jul 2019 11:54

AW: Decompress einer gz-Datei mit NULL-Zeichen
 
Ich hab mal vor einiger Zeit eine Unit für Gzip gemäß RFC 1952 erstellt, kannst du ja mal probieren:
http://yat.qa/DEV/src/RedeemerGzip.pas
Das Feld Zlib ist dann ein Zlib-kompatibler Stream, den sollte man mit dem DecompressionStream lesen können.

Jumpy 4. Jul 2019 14:40

AW: Decompress einer gz-Datei mit NULL-Zeichen
 
Vielleicht kann man in dem Stream LUnzip einfach die #0 ersetzen oder man guckt mal wieso TStringliast.LoadFromStream bei einer #0 abbricht.

dummzeuch 4. Jul 2019 14:48

AW: Decompress einer gz-Datei mit NULL-Zeichen
 
Zitat:

Zitat von philipp.hofmann (Beitrag 1435919)
Hi,

bisher decompresse ich gz-Dateien mit folgendem Code:

Jetzt funktioniert dies leider nicht mit gz-Dateien, wo ein NULL-Zeichen enthalten ist. Dort enthält das Result dann nur den File-Inhalt bis zum NULL-Zeichen.

Wo genau gibt es das NULL-Zeichen? In der gz-Datei oder in der unkomprimierten Datei?

Falls in der gz-Datei, sollte das eigentlich kein Problem darstellen, da dann durch das un-gzip daraus wieder eine Datei ohne NULL-Zeichen enstehen sollte.

Falls in der unkomprimierten Datei, wundert es mich, dass der Umweg -> als Datei dekomprimieren -> diese Datei in Stringlist laden funktioniert.

philipp.hofmann 4. Jul 2019 17:06

AW: Decompress einer gz-Datei mit NULL-Zeichen
 
Hi,

in #5 hängt eine ZIP-Datei mit einem Beispiel-Projekt und eben dieser gz-Datei. Das #NUL-Zeichen ist in der Textdatei, die als gz gezippt wurde. Ich bin nur der Leser dieser gz-Datei, daher kann ich nichts dafür, dass dieses Zeichen dort ist wo es ist (missbrauche also nichts). Die Datei ist ANSI codiert, es macht aber keine Unterschied, ob ich dies mit angebe oder nicht. Ich "traue" an der Stelle auch der Anzeige in Notepad++, wo ich das #NUL-Zeichen sehe.

Ich werde dann mal tiefer reinschauen müssen, weil es ja interessanterweise geht, wenn ich TMemo.LoadFromStream aufrufe, aber nicht bei meinem TStringList.LoadFromStream.

Grüße, Philipp

juergen 4. Jul 2019 17:19

AW: Decompress einer gz-Datei mit NULL-Zeichen
 
Hallo,

Evtl. könnte nachfolgendes helfen:
https://www.delphipraxis.net/1392556-post14.html

philipp.hofmann 5. Jul 2019 07:42

AW: Decompress einer gz-Datei mit NULL-Zeichen
 
Ja, es liegt an TStrings.setTextStr, d.h. hat mit dem Entpacken an sich nichts zu tun.
Dies überschreibe ich nun, um mit solch bösen gz-Files umzugehen. Danke.

Luckie 5. Jul 2019 10:33

AW: Decompress einer gz-Datei mit NULL-Zeichen
 
Es liegt an der Ausgabe. In Windows ist die #0 das Stringendezeichen. Das heißt, Windowscontrolls brechen an dieser Stelle die Ausgabe ab.

Klaus01 5. Jul 2019 10:42

AW: Decompress einer gz-Datei mit NULL-Zeichen
 
.. nicht nur die Ausgabe,
die StringList bricht auch beim Einlesen .loadFromStream bei #0 ab.
Also hinter #End Header'#0'

Grüße
Klaus


Alle Zeitangaben in WEZ +1. Es ist jetzt 06:46 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz