Datei binär lesen mit TFileStream
-
dschensky schrieb:
Also bei TFileStream kann ich mir das eigentlich gar nicht vorstellen.
Doch (bei manchen aber, nicht bei allen), glaube mir.
dschensky schrieb:
[...] globale Variable _fmode (siehe CB-Hilfe)[...]
Danke für den Tipp, dschensky! Werde es mir morgen anschauen. Heute ist alles wie verhext.
Schöne Grüße
-
dschensky schrieb:
Ansonsten gibt es da noch die globale Variable _fmode (siehe CB-Hilfe), die Dateioperationen beeinflusst. Vielleicht hilft Dir das irgendwie weiter...
_fmode hat leider auch nicht geholfen.
Ich habe die EPS-Datei nochmal genauer kontrolliert. Das Lesen hört immer bei dem HEX-Zeichen 00 auf, und nur bis dahin gelesenen Zeichen werden geliefert.Wie gesagt, wenn ich fopen verwende und die Datei Zeichen für Zeichen lese, dann klappt es. Ich werde vorerst dabei bleiben, auch wenn es ziemlich langsamer ist.
Danke nochmal, dschensky!
-
Zeig mal den Lese-Code.
-
AnsiString __fastcall ReadEPSFile(AnsiString sEPSPfad) { AnsiString sRet = ""; char c; FILE *in = fopen(sEPSPfad.c_str(), "r+b"); if(in == NULL) return ""; while (!feof(in)) { c = fgetc(in); sRet += c; }; fclose(in); return sRet; }
-
Mit TFileStream:
AnsiString __fastcall ReadEPSFile(AnsiString sEPSPfad) { _fmode = O_BINARY; TFileStream *fsEPSFile = new TFileStream(sEPSPfad.c_str(), fmOpenRead); int iSize = fsEPSFile->Size; fsEPSFile->Position = 0; char *cEPSFile = new char[iSize + 1]; int iReadBytes = fsEPSFile->Read(cEPSFile, iSize); cEPSFile[iReadBytes] = 0; AnsiString sRet(cEPSFile); delete[] cEPSFile; delete fsEPSFile; return sRet; }
-
Wusst' ichs doch.
Nun, ganz Einfach wieso das nicht geht wie dus geschrieben hast:
Binäre Daten kann man nicht mit String-Funktionen verwalten!
Und von _fmode würde ich die Finger generell lassen.
-junix
-
junix schrieb:
Binäre Daten kann man nicht mit String-Funktionen verwalten!
Aha! Gut zu wissen. Danke!
Wie kann ich sonst eine (EPS)Datei in einem RichEdit anzeigen? Wie gesagt, Mit LoadFormFile kriege ich es nur bis zum 1. auftretenden HEX-Zeichen 00 gelesen. Mit TFileStream ist es genauso. (im Wordpad oder Notepad wird der ganze Inhalt angezeigt)Gibt es da noch andere Möglichkeiten?
Dankeschön.
-
xy schrieb:
[...]Mit LoadFormFile kriege ich es nur bis zum 1. auftretenden HEX-Zeichen 00 gelesen. Mit TFileStream ist es genauso.[..]
... was nicht direkt an TFileStream sondern viel mehr am AnsiString Objekt liegt, da dieses ja - logischer weise - annimmt, dass es sich um einen String handelt, wenn man diesem einen Char-Zeiger übergibt.
Der Trick den Word- und Notepad verwenden ist relativ simpel: Sie fahren durch den gelesenen Puffer und ersetzen alle 0x00 (und ev. noch weitere Steuerzeichen) durch einen Whitespace (0x20). Etwas ähnliches würde ich dir ebenfalls anraten.
(Du hast den Puffer ja schon als char-Puffer, also schnell mit dem Zeiger durchfahren und fertig. Geht relativ fix.)
Ansonsten verwaltet man übrigens Bin. Puffer mit den allseits beliebten mem*-Funktionen (memset, memcpy, etc. pp)
-junix
-
junix schrieb:
Der Trick den Word- und Notepad verwenden ist relativ simpel: Sie fahren durch den gelesenen Puffer und ersetzen alle 0x00 (und ev. noch weitere Steuerzeichen) durch einen Whitespace (0x20). Etwas ähnliches würde ich dir ebenfalls anraten.
Werde ich gleich mal probieren.
Herzlichen Dank für Deine Hilfe, junix!
xy
-
junix schrieb:
[...]Du hast den Puffer ja schon als char-Puffer, also schnell mit dem Zeiger durchfahren[...]
Ich bin Deinem Rat befolgt und hatte versucht den char-Puffer zu parsen. ICh habe aber festgestellt, daß schon da der Inhalt nach dem 1. auftretenden 0x00 fehlt. Ich habe es hier kommentiert:
TFileStream *fsEPSFile = new TFileStream(Edit1->Text.c_str(), fmOpenRead); int iSize = fsEPSFile->Size; //iSize = 5937 fsEPSFile->Position = 0; char *cEPSFile = new char[iSize + 1]; int iReadBytes = fsEPSFile->Read(cEPSFile, iSize); //iReadBytes = 5937 cEPSFile[iReadBytes] = 0; //cEPSFile enthält nur folgendes: ÅÐÓÆP int iL = strlen(cEPSFile); // iL = 6
Liegt das an Read-Methode?
Danke
xy
-
xy schrieb:
TFileStream *fsEPSFile = new TFileStream(Edit1->Text.c_str(), fmOpenRead); int iSize = fsEPSFile->Size; //iSize = 5937 fsEPSFile->Position = 0; char *cEPSFile = new char[iSize + 1]; int iReadBytes = fsEPSFile->Read(cEPSFile, iSize); //iReadBytes = 5937 cEPSFile[iReadBytes] = 0; //cEPSFile enthält nur folgendes: ÅÐÓÆP int iL = strlen(cEPSFile); // iL = 6
Wieso schliesst du den String NULL ab, obwohl noch gar kein String sondern binäre Daten im Puffer liegen? Wo liegt die Funktion in der du die 0x00er ersetzt?
-junix
-
junix schrieb:
Wieso schliesst du den String NULL ab, obwohl noch gar kein String sondern binäre Daten im Puffer liegen?
Wo mache ich das? Entschuldigung, aber ich blicke nicht mehr durch.
Wenn Du das hier meinst:char *cEPSFile = new char[iSize + 1];
dann spielt es _in diesem Fall_ keine Rolle, weil das Lesen der Datei schon vor dem 1. auftretenden 0x00 aufhört. (In diesem Fall ist dieses das 7. Zeichen, und so bekomme ich nur 6 Zeichen geliefert.)
Ich habe es auch schon mit iSize (ohne +1) versucht. Gleiches Ergebnis.junix schrieb:
Wo liegt die Funktion in der du die 0x00er ersetzt?
die kommt unmittelbar nach dem im letzten Beitrag geposteten Code.
Aber wie kann ich sie auf den char-Puffer anwenden, wenn er nicht den ganzen Datei-Inhalt enthält, wiel er, wie gesagt, vor dem 1. auftretenden 0x00 aufhört? Das ist ja mein Problem.Danke nochmals
xy
-
xy schrieb:
junix schrieb:
Wieso schliesst du den String NULL ab, obwohl noch gar kein String sondern binäre Daten im Puffer liegen?
Wo mache ich das? Entschuldigung, aber ich blicke nicht mehr durch.
Das hier:
cEPSFile[iReadBytes] = 0; //cEPSFile enthält nur folgendes: ÅÐÓÆP
xy schrieb:
weil das Lesen der Datei schon vor dem 1. auftretenden 0x00 aufhört.
detektiert wodurch?
xy schrieb:
Ich habe es auch schon mit iSize (ohne +1) versucht. Gleiches Ergebnis.
Das ist naheliegend.
xy schrieb:
junix schrieb:
Wo liegt die Funktion in der du die 0x00er ersetzt?
die kommt unmittelbar nach dem im letzten Beitrag geposteten Code.
Überleg dir nochmals genau ob das der richtige Ort ist. Und schau nochmals die letzten hmmm 4-5 Beiträge in diesem Thread an...
xy schrieb:
Aber wie kann ich sie auf den char-Puffer anwenden, wenn er nicht den ganzen Datei-Inhalt enthält, wiel er, wie gesagt, vor dem 1. auftretenden 0x00 aufhört?
Das Problem ist primär mal, wie du festgestellt hast, dass der Dateiinhalt nicht komplett gelesen wird. Solange wir diese Detektionsmethode nicht erörtert haben, brauchen wir gar nicht weiter zu diskutieren...
-junix
-
Erst einmal vielen Dank, junix!
junix schrieb:
xy schrieb:
weil das Lesen der Datei schon vor dem 1. auftretenden 0x00 aufhört.
detektiert wodurch?
Ich habe die EPS-Datei im HEX-Editor geöffnet und festgestellt, daß das 7. Zeichen ein HEX 00 ist. dann hatte ich folgendes in meinem Code geändert:
fsEPSFile->Position = 8; //statt 0
Danach wurde wieder nur bis zum nächsten HEX 00 gelesen. Dann Position verschoben -> wieder bis zum 0x00 gelesen usw...
Ok, das hier funktioniert:
AnsiString sRet = ""; TFileStream *fsEPSFile = new TFileStream(Edit1->Text, fmOpenRead); int iSize = fsEPSFile->Size; fsEPSFile->Position = 0; char *cEPSFile = new char[iSize + 1]; int iReadBytes = fsEPSFile->Read(cEPSFile, iSize); //cEPSFile[iReadBytes] = 0; //Wenn ich diese Zeile auskommentiere, ändert sich in diesem Fall hier nichts. //cEPSFile enthält weiterhin nur die sechs Zeichen: ÅÐÓÆP //i<strlen(cEPSFile) -> 6. //i<iReadBytes -> 5937. ==> funktioniert. for(int i=0; i<iReadBytes/*strlen(cEPSFile)*/; i++) { if(cEPSFile[i] == 0x00) sRet += 0x20; else sRet += cEPSFile[i]; } RichEdit1->Lines->Clear(); RichEdit1->Lines->Add(sRet); delete[] cEPSFile; delete fsEPSFile;
Was ich aber nicht verstehe, ist, wenn der char-Puffer in allen Fällen nur die ersten sechs Zeichen enthält (Länge ist demzufolge = 6), wieso funktioert es dann wenn ich in der for-Schleife i<iReadBytes (5937) schreibe. Wo sind die restlichen 5931 Zeichen im char-Puffer versteckt?!
Entschuldigung, aber es reicht mir nicht, daß es jetzt funktioniert, ich möchte es auch gerne verstehen.
Nochmals danke für die Hilfe!
xy
-
xy schrieb:
Was ich aber nicht verstehe, ist, wenn der char-Puffer in allen Fällen nur die ersten sechs Zeichen enthält (Länge ist demzufolge = 6),
Ich zitiere mich nur ungern selber, aber trotzdem:
junix schrieb:
Binäre Daten kann man nicht mit String-Funktionen verwalten!
Du hast die Länge allerdings mit strlen() ermittelt. Dies verletzt die obige Regel.
xy schrieb:
wieso funktioert es dann wenn ich in der for-Schleife i<iReadBytes (5937) schreibe. Wo sind die restlichen 5931 Zeichen im char-Puffer versteckt?!
Nirgendwo. Es wurden 5931 Zeichen gelesen und in den Char-Puffer geschrieben. Das Problem ist die definition von C, dass ein String mit 0x00 abgeschlossen ist. Alle Stringfunktionen funktionieren dementsprechend nur bis zum 1. Auftreten von 0x00.
Will man das verhindern, brauchts binäre Funktionen. (Statt str*-Funktionen, mem*-Funktionen) welche die Kopier-, Verschiebe-, Zusammenhängaufgaben, etc. verrrichten.Das war auch der Grund wieso ich nochmals explizit gefragt hatte, wie du ermittelt hast, dass die Read-Funktion nach 6 Zeichen aufgehört hat. (Ich dachte mir schon, dass du dich mit den 6 Zeichen auf das strlen()-Ergebnis bezogen hast, wollte das nur nochmals verifizieren).
xy schrieb:
Entschuldigung, aber es reicht mir nicht, daß es jetzt funktioniert, ich möchte es auch gerne verstehen.
No use to excuse... Im Gegenteil. Von dieser Einstellung könnte sich hier so manch einer eine dicke Scheibe abschneiden.
Wenn du noch weitere Fragen zu dem THema hast: Ungeniert nachhaken. Ich neige manchmal dazu, mich etwas umständlich zu artikulieren (o;-junix
-
ICh kann meinen Dank in Worten nicht ausdrucken!
Und wasjunix schrieb:
Ich neige manchmal dazu, mich etwas umständlich zu artikulieren (o;
angeht, verstehe ich Dich vollkommen. Mit Deiner "erzieherischen" Methode bringst Du den Fragenden auch zum "Mitdenken". So kommt es dazu, daß er vielleicht alleine auf die Lösung kommt, was immer besser ist.
Schöne Grüße und hezlichen Dank nochmal
xy