![]() |
Datei mit "#0" schreiben?
Ich wollte ein bisschen mit Dateien experimentieren, und hatte die Idee, dass ja TStringList.LoadFromFile() bis zum #0 liest. Ich wollte aber weiter Informationen hinterlegen, und dachte mir:
Code:
... Wie ist das möglich?
Normaler
Inhalt #0 Extra Inhalt#0 Ich habe da an TFileStream gedacht, aber ich kenne mich da nicht aus, und habe auch danach gesucht weis aber nicht, wie ich die Suche einschränken könnte... Also das soll der Effekt sein: Ich möchte eine Datei einlesen, bis zum ersten #0 lesen, dass dann als string bearbeiten und dann bis zum 2. #0 lesen (wenns eins gibt) und das als weiteren String bearbeiten... |
Re: Datei mit "#0" schreiben?
Soweit ich weiß sind Delphi-Strings nullterminierte Char-Arrays, das heißt, an der Stelle, wo ein #0 ist, ist für Delphi der String zu Ende. Du wirst wohl nicht umhinkommen, das ganze "per Hand" zu laden, also mit einem Filestream und immer schön schauen, ob grad ein #0 da ist.
Ein Filestream lässt sich recht leicht bedienen:
Delphi-Quellcode:
var buf: Char;
str: String; fs: TFileStream; begin fs:=TFileStream.Create('Dateiname', fmOpenRead, fmShareDenyWrite); try while fs.Position<fs.Size do begin fs.Read(buf, 1); if buf=#0 then //... else str:=str+buf; end; finally fs.Free; end; end; |
Re: Datei mit "#0" schreiben?
Ah danke ;) Jetzt mal ne Frage, die nicht so richtig dazu passt, aber mir dennoch wichtig ist:
"Muss" ich denn den 2. Teil (nach #0) auch irgendwie mit "#0" o.s.ä. beenden, oder tuts das "fs.size"? |
Re: Datei mit "#0" schreiben?
Zitat:
Delphi-Quellcode:
DelphiStrings haben eine Längenangabe und da nur diese ausgewertet wird, is eine #0 im String völlig irrelevant.
S := '123'#0'456';
If S = '' Then ; << mach hier mal einen Breakpoint und schau was in S drin ist ;) Bei Umwandlungen in PChar, wird die Längenangabe nicht beachtet, aber dafür dann die #0. @Zise: es wäre dennoch einfacher nicht die #0 zu verwenden ... #1..#7, #9, #11, #12 oder #14..#31 bieten sich doch auch an? > Steuerzeichen (#0..#31) - CR, LF, Tab (#8 #10 #13) Dann kannst du alles mögliche zum Einlesen verwenden und auch die bekannten Funktionen zum String-Zerlegen (ziehe CodeLib) könnte z.B. mit dem Zeichen #1 wunderschön genutzt werden. |
Re: Datei mit "#0" schreiben?
Das wichtige ist eben, dass mit dem Aufruf TStringList.LoadFromFile er am Stoper abbricht ... Und ich habe schon selber erfahren müssen, dass es mit #0 geht...
PS: Das einlesen klappt super ^^ Danke 3 of 8 ;) |
Re: Datei mit "#0" schreiben?
Zitat:
Delphi-Quellcode:
Oder, als Assembler-Version:
var str: String;
begin str:='wuppdi'; showmessage(inttostr(PByte(Cardinal(@str[6])+1)^)); end;
Delphi-Quellcode:
Wie du siehst, kommt immer 0 raus. Warum? Damit Strings sich schnell und leicht in PChars konvertieren lassen und man nicht jedesmal Speicher neu reservieren muss, wenn man mal schnell nen String an die WinAPI schickt.
function blubb(s: String): Byte;
asm mov al, byte ptr eax+6 end; procedure TForm1.FormCreate(Sender: TObject); var str: String; begin str:='wuppdi'; showmessage(inttostr(blubb(str))); end; Allerdings ist der String 'wup'#0'di' für Delphi tatsächlich 'wup'#0'di' und nicht 'wup'. Da habe ich mich getäuscht. Sobald man jedoch versucht, in per showmessage o.ä. auszugeben, bleibt nur noch ein 'wup' übrig. |
Re: Datei mit "#0" schreiben?
Stichwort : TInifile. Würde ich mir mal ansehen. Mit #0 oder WinApi am Betriebssystem rumzufummeln würde ich mir gründlich überlegen.
|
Re: Datei mit "#0" schreiben?
@3_of_8: das mit dem abschließendem #0 in String hab ich nie bezweifelt ... nutze es ja selber für 'ne schnelle String-PChar-Konvertierung, ohne PChar(S) aus.
Aber warum es mit ShowMessage nicht geht ist recht einfach erklärt ... dieses übergibt ja intern zum Darstellen den String an eine WinPAI-Funktion auf, welche ja die Strings als PChar entgegen nimmt. :zwinker: @xZise: TStringList.LoadFromFile ließt die gesamte Datei ein, nur ruft es danach TStringList.SetTextStr auf, welches alles ab #0 wieder abschneitet/löscht. Da du ja wegen der (gewollten) #0 eh die Dateien mit 'nem eigenem Programm erstellen muß, wie wäre es dann mit der eingebauten Längenangabe? Dieses würde dann auch das einlesen beschleunigen/vereinfachen, da ja gleich bekannt wäre, wie lang der String wäre. Also jeweils die Länge (LongInt) und nachfolgend den Stringinhalt speichern. Sozusagen:
Delphi-Quellcode:
(womit eingelesen/gespeichert wird, is dir überlassen ... also ob Stream, oder was Anderes)
i := Length(S);
Write(@i, SizeOf(i)); Write(PChar(S), i); Read(@i, SizeOf(i)); SetLength(S, i); Read(PChar(S), i); |
Re: Datei mit "#0" schreiben?
So... Ich will jetzt mein Vorhaben genauestens beschreiben:
Es gibt ein Dateiformat, welches eigentlich ich nicht bestimmen kann. Ich kann eben nur darauf hoffen, dass der Programmierer "TStringList.LoadFromFile" benutzt. Ich kam aber auf die Idee weitere Daten da zu hinterlegen. Wie macht man das ohne das Programm zu verwirren: Man tut so (für TStringList) so, als sei die Datei da zuende obwohl dahinter noch was ist, was es aber nicht interpretieren kann. Deshalb habe ich gedacht, dass nach den Informationen, welche das Programm versteht, ein #0 zu setzten. Während mein Programm, welches auch damit arbeitet dies berücksichtigt und die Daten dahinter ausliest. Deshalb kann ich das Format nur mit den #0 verändern.
Code:
Das grüne kann ich ändern...
[color=#0000ff]Datei[/color]
[color=#7f00ff]#0[/color] [color=#00ff3f]Meine Daten[/color] Und das Blaue kann ich nicht ändern... Zitat:
Zitat:
Zitat:
Zitat:
[edit]Es stellt sich mir die Frage, wie ich ein #0 schreiben kann... mit TFileStream! Das tuts net:
Delphi-Quellcode:
[/edit]
level.Write(Pointer(#0)^, Length(#0));
|
Re: Datei mit "#0" schreiben?
Zitat:
|
Re: Datei mit "#0" schreiben?
Bei meinem
![]() Da ich sowieso eine Klasse von TStringList ableiten mußte, habe ich deshalb gleich deren Routine LoadFromStream(..) ersetzt. Diese Routine rief eine andere namens SetTextStr(..) auf, welche auf #0 prüfte. Den Teil hab' ich geändert (Minimaler Eingriff in den Original Code), danach hat die abgeleitete stringlist brav bis zum Ende gelesen. Vielleicht reicht ja so ein Eingriff bei Deinem Problem auch - zumindest für's Lesen? (Siehe Source von UnitUsage, Datei DelDirective.pas) Ansonsten hat ja TStringList mit #0 keine Probleme - Beim Schreiben wird's halt wieder klemmen ;) Gruß Michael |
Re: Datei mit "#0" schreiben?
Und genau mit dem schreiben hab ich das Problem ^^ Weil solange ich nirgens eine Datei mit #0 schreiben kann, kann ich auch nicht testen, ob er auch richtig liest (obwohl bisher es brav aussieht ^^)
|
Re: Datei mit "#0" schreiben?
Pointer(#0)^? Ein Pointer auf ein Literal? Aua.
Delphi-Quellcode:
var fs: TFileStream;
buf: Char; begin //... fs.Write(buf, 1); //... end; |
Re: Datei mit "#0" schreiben?
[Editiert, um den größten Krampf meiner letzten Antwort loszuwerden. Hab' irgendwie das Thema verfehlt... :oops: ]
TStringList schreibt zumindest den Null Charakter brav raus (SaveToFile, welches intern einen TFileStream verwendet), lediglich das ReadFromFile fängt unnötigerweise mit dem Interpretieren an. Mit TStringList sollte es also wenig Probleme geben, solche Dateien zu erzeugen (Delphi 6). Allerdings wird #0 als Zeilenumbruch interpretiert (Siehe z.B. Classes.pas procedure TStrings.SetTextStr(..); Das könnte einem beim Arbeiten mit der StringListe dann doch mal was verhageln... Gruß Michael |
Re: Datei mit "#0" schreiben?
@xZise: Leg ein Array of Byte an, das die Länge der Dateigröße besitzt. Anschließend liest du die Datei über FileOpen(), FileRead() in dein Array ein. Mit einer For-Schleife durchsuchst du nun Zeichen für Zeichen dein Array of Byte und kopierst dir die Segmente heraus die du benötigt. (zum Bleistift mit Copy() sofern es sich um ANSI-Dateien handelt) Den Dateiaufbau sollte man möglichst genau kennen... Abschließend noch ein FileClose ausführen. Fertig.
|
Re: Datei mit "#0" schreiben?
Hallo,
warum nicht nach dieser Methode: Seek(eof) Zusatzdaten anhängen und zum einlesen: Seek(eof) zurücklesen bis #0 Wär jetzt nur mal so eine grobe Idee ohne dass ich den Code grad im Kopf hab, aber dass müsste doch funktionieren. Gruß Matthias |
Re: Datei mit "#0" schreiben?
Weil file of <typ> veraltet ist und es dafür FileStreams gibt?
|
Re: Datei mit "#0" schreiben?
Also... Danke an den Borg (^^)... Jetzt funktioniert es wunderbar... Er trennt korrekt, und schreibt auch so wie ich das will ;) thx ^^
PS: Wie kann man den im Notepad ein #0 einfügen? |
Re: Datei mit "#0" schreiben?
In Notepad geht das nicht.
Delphi-Quellcode:
und dann einfach mit dem String arbeiten, die ganze datei ist da drin
var s: String;
begin fm := TfileStream.create(...); SetLength(s, fm.size); Read(s[1], fm.size); fm.free; end; ein String endet immer mit #0, aber er wird nicht bei einer #0 abgeschnitten sondern die Länge wird mitgespeichert bla := 'blub'#0'hallo' ist ein gültiger String length(bla) = 10 PChar(bla) = 'blub' bla[length(bla)+1] = #0 |
Alle Zeitangaben in WEZ +1. Es ist jetzt 20:35 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz