Autor Beitrag
maxk
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 1696
Erhaltene Danke: 1

Win XP, Debian Lenny
Delphi 6 Personal
BeitragVerfasst: Do 06.02.03 11:54 
Ich schreibe mit folgender Procedure:
ausblenden 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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2596

Win7
D2006 WIN32, .NET (C#)
BeitragVerfasst: 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:

ausblenden 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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 896

Win XP, Suse 8.1
Delphi 4/7/8 alles prof
BeitragVerfasst: Do 06.02.03 12:07 
hi, ich glaub dafür gibt es TStringStream 8)

mfg mx
maxk Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 1696
Erhaltene Danke: 1

Win XP, Debian Lenny
Delphi 6 Personal
BeitragVerfasst: 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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2596

Win7
D2006 WIN32, .NET (C#)
BeitragVerfasst: 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:
ausblenden Quelltext
1:
2:
3:
SaveStrToStream(FS,X);

LoadStrFromStream(FS,X);


Cu, :)
Udontknow
DaRkFiRe
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 526

WinXP Home & Professional
C, C++, Delphi
BeitragVerfasst: Fr 07.02.03 00:17 
ausblenden 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:

ausblenden 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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2596

Win7
D2006 WIN32, .NET (C#)
BeitragVerfasst: 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? :wink:

Schau dir noch mal die geposteten Funktionen an.

Cu, :)
Udontknow
maxk Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 1696
Erhaltene Danke: 1

Win XP, Debian Lenny
Delphi 6 Personal
BeitragVerfasst: Fr 07.02.03 10:41 
Die Länge des Strings ist mir ja bekannt!
ausblenden Quelltext
1:
2:
SetLength(Str,20);
FS.ReadBuffer(Str[1],20);

und andersherum:
ausblenden Quelltext
1:
FS.WriteBuffer(Pointer(Str)^,length(Str));					


Das Funktioniert (es sei denn ich habe einen Schreibfehler im Quelltext :oops: ).

_________________
Ein Computer wird das tun, was Du programmierst - nicht das, was Du willst.
Udontknow
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2596

Win7
D2006 WIN32, .NET (C#)
BeitragVerfasst: 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
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 526

WinXP Home & Professional
C, C++, Delphi
BeitragVerfasst: 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

ausblenden 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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 2266
Erhaltene Danke: 4

Vista
D6 Prof, D 2005 Pro, D2007 Pro, DelphiXE2 Pro
BeitragVerfasst: 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
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 526

WinXP Home & Professional
C, C++, Delphi
BeitragVerfasst: 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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 896

Win XP, Suse 8.1
Delphi 4/7/8 alles prof
BeitragVerfasst: 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 :wink: 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