| Autor |
Beitrag |
maxk
      
Beiträge: 1696
Erhaltene Danke: 1
Win XP, Debian Lenny
Delphi 6 Personal
|
Verfasst: Do 06.02.03 11:54
Ich schreibe mit folgender Procedure:
Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10:
| var FS:TFileStream; X:string; begin FS:=TFileStream.Create('C:\Test.TXT',fmCreate); FS.Size:=5; FS.Position:=0; X:='12345'; FS.WriteBuffer(X,length(X)); FS.Free; end; |
Ich bekomme keine Fehlermeldung, allerdings besteht meine Datei (C:\Text.TXT) danach nur noch aus 5 Steuerzeichen statt aus dem Text von X (12345).
Was mache ich falsch?
maxk
_________________ Ein Computer wird das tun, was Du programmierst - nicht das, was Du willst.
|
|
Udontknow
      
Beiträge: 2596
Win7
D2006 WIN32, .NET (C#)
|
Verfasst: Do 06.02.03 12:00
Hi!
Strings kannst du aufgrund ihrer dynamischen Länge nicht einfach so in einen Stream speichern. Du müsstest entweder Shortstrings (z.B: String[50]) verwenden oder folgende Funktionen benutzen:
Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19:
| procedure SaveStrToStream(const Stream: TStream; const Value: String); //Schreibt einen dynamischen String in einen Stream var Len: Word; begin Len := Length(Value); Stream.WriteBuffer(Len, SizeOf(Len)); if Len > 0 then Stream.WriteBuffer(Pointer(Value)^, Len); end;
procedure LoadStrFromStream(const Stream: TStream; var Str: String); //Liest einen dynamischen String aus einem Stream var Len: Word; begin Stream.ReadBuffer(Len, SizeOf(Len)); SetLength(Str, Len); if Len > 0 then Stream.ReadBuffer(Pointer(Str)^, Len); end; |
Cu,
Udontknow
|
|
maximus
      
Beiträge: 896
Win XP, Suse 8.1
Delphi 4/7/8 alles prof
|
Verfasst: Do 06.02.03 12:07
hi, ich glaub dafür gibt es TStringStream
mfg mx
|
|
maxk 
      
Beiträge: 1696
Erhaltene Danke: 1
Win XP, Debian Lenny
Delphi 6 Personal
|
Verfasst: Do 06.02.03 12:10
Geht nicht!
Aber wenn ich den ersten Aufruf von WriteBuffer weglasse funzt es.
Thx,
maxk
_________________ Ein Computer wird das tun, was Du programmierst - nicht das, was Du willst.
|
|
Udontknow
      
Beiträge: 2596
Win7
D2006 WIN32, .NET (C#)
|
Verfasst: Do 06.02.03 12:30
@Maximus:
Was, wenn du noch andere Sachen im Stream hast als Strings? Z.B. Records oder Integerwerte hinter dem String? Dann scheidet TStringStream aus.
@MaxK
Du musst auch zum Einlesen dann die Prozedur LoadStrFromStream benutzen.
Also:
Quelltext 1: 2: 3:
| SaveStrToStream(FS,X);
LoadStrFromStream(FS,X); |
Cu,
Udontknow
|
|
DaRkFiRe
      
Beiträge: 526
WinXP Home & Professional
C, C++, Delphi
|
Verfasst: Fr 07.02.03 00:17
Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10:
| var FS:TFileStream; X:string; begin FS:=TFileStream.Create('C:\Test.TXT',fmCreate); FS.Size:=5; FS.Position:=0; X:='12345'; FS.WriteBuffer(X,length(X)); FS.Free; end; |
filestreams können (so glaube ich mal, gelesen zu haben) keinen festen größen zugewiesen werden
mit writebuffer kann man nicht auf den string selbst zeigen - das ist nur ein zeiger (wegen der delphi-internen verarbeitung von zeichenfolgen)
ich würd's so machen wollen:
Quelltext 1: 2: 3: 4: 5: 6: 7: 8:
| var FS:TFileStream; X:string; begin FS:=TFileStream.Create('C:\Test.TXT',fmCreate); X:='12345'; FS.Write(X[1],length(X)); FS.Free; end; |
_________________ Lang ist der Weg durch Lehren - kurz und wirksam durch Beispiele! Seneca
|
|
Udontknow
      
Beiträge: 2596
Win7
D2006 WIN32, .NET (C#)
|
Verfasst: Fr 07.02.03 09:39
@DarkFire: Ähnlich machen das ja auch oben gepostete Funktionen. Sie tun aber noch mehr.
Wie bekommst du beim Lesen heraus, wie lang der String ist, der nun eingelesen werden muss?
Schau dir noch mal die geposteten Funktionen an.
Cu,
Udontknow
|
|
maxk 
      
Beiträge: 1696
Erhaltene Danke: 1
Win XP, Debian Lenny
Delphi 6 Personal
|
Verfasst: Fr 07.02.03 10:41
Die Länge des Strings ist mir ja bekannt!
Quelltext 1: 2:
| SetLength(Str,20); FS.ReadBuffer(Str[1],20); |
und andersherum:
Quelltext 1:
| FS.WriteBuffer(Pointer(Str)^,length(Str)); |
Das Funktioniert (es sei denn ich habe einen Schreibfehler im Quelltext  ).
_________________ Ein Computer wird das tun, was Du programmierst - nicht das, was Du willst.
|
|
Udontknow
      
Beiträge: 2596
Win7
D2006 WIN32, .NET (C#)
|
Verfasst: Fr 07.02.03 13:03
Na gut, wenn du die Länge kennst, geht es. Stelle dir aber mal folgendes vor: Du musst 1000 solcher Strings speichern, 90% davon sind aber leer (''). Deine Dateigrösse würde immer konstant 20000 betragen, benutzt du aber die Funktionen, die ich gepostet habe, so ist die Datei viel kleiner, da du so nur ein Word (=2Byte) für die Länge und den vorhandenen Text speicherst.
Für leere Strings würdest du nur 2 Byte benötigen, mit deiner Methode dagegen 20 (Faktor 10!). Haben die Strings eine Länge von 20, so benötigst du mit den Routinen nur unwesentlich mehr (22 Byte).
Und wenn irgendein String doch mal länger sein sollte als 20 Zeichen, hast du Pech gehabt...
Cu,
Udontknow
|
|
DaRkFiRe
      
Beiträge: 526
WinXP Home & Professional
C, C++, Delphi
|
Verfasst: Fr 07.02.03 13:48
Naja - dann müsste man höchstens eine Art Load / Save Engine schreiben, die nach folgendem Prinzip verfährt:
Schreiben:
Länge des Strings (Integer @ 4 Byte / 32 Bit)
String an sich
Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17:
| procedure writeStringToStream(Stream:TStream; S:STRING); var I:INTEGER; begin I:=LENGTH(S); Stream.Write(I,SIZEOF(INTEGER)); Stream.Write(S[1],I); end;
function readStringFromStream(Stream:TStream):STRING; var I:INTEGER; var R:STRING; begin Stream.Read(I,SIZEOF(INTEGER)); R:=STRINGOFCHAR(#0,I); Stream.Read(R[1],I); Result:=R; end; |
_________________ Lang ist der Weg durch Lehren - kurz und wirksam durch Beispiele! Seneca
|
|
Keldorn
      
Beiträge: 2266
Erhaltene Danke: 4
Vista
D6 Prof, D 2005 Pro, D2007 Pro, DelphiXE2 Pro
|
Verfasst: Fr 07.02.03 13:53
habt ihr euch schonmal Twriter/Treader angeschaut?
da gibt es bereits haufenweise Procs zum lesen und speichern unterschiedlichester Variablentypen
Frank
_________________ Lükes Grundlage der Programmierung: Es wird nicht funktionieren.
(Murphy)
|
|
DaRkFiRe
      
Beiträge: 526
WinXP Home & Professional
C, C++, Delphi
|
Verfasst: Fr 07.02.03 14:25
Naja - ich glaube, das waren die abstrakten Komponenten für das Schreiben in Delphi-Anwendungen - also für Komponenten selbst ( Binär-daten speichern, usw. )
_________________ Lang ist der Weg durch Lehren - kurz und wirksam durch Beispiele! Seneca
|
|
maximus
      
Beiträge: 896
Win XP, Suse 8.1
Delphi 4/7/8 alles prof
|
Verfasst: Fr 07.02.03 14:37
Na klar,
da hat keldron völlig recht. Die filer klassen benutz ich auch immer wieder gerne...die dinger sind einfach genial, wenn man dynamische datei formate erstellen will.
@DaRkFiRe: ich glaub sie sind weder abstrakt, noch komponeten  Man kann damit binäre, als auch text-formate speichern. Die DFM-routinen benutzen sie auch, da hast du recht.
Man kann sie prima zB in seiner eigene klasse einbauen, um solche prozeduren wie: saveToStream, loadFromStream, saveToFile, etc. zu machen.
mfg maximus
|
|