![]() |
Filestream, string anhängen
Hi leute,
Ich bin am verzweifeln .. Ich möchte einen string an eine datei anhängen, und mit der datei den string auslesen.. dieser code klappt super.. Ich habe hier einen string angehangen, und direkt wieder ausgelesen..
Delphi-Quellcode:
so.. jetzt wollte ich aber den string von einer anderen EXE auslesen (später dann die background.exe)
var fs:tfilestream; s,s1:string;i:integer;
begin fs:=tfilestream.Create('C:\background.exe', fmOpenReadWrite or fmShareExclusive); try i:=fs.Seek(0, soFromEnd); s:='[test]'; fs.Write(s,sizeOf(s)); fs.Seek(i, soFromBeginning); fs.Read(s1,sizeOf(s1)); showmessage(s1); finally fs.Free; end;
Delphi-Quellcode:
und dann kommt immer eine zugriffsverletztung, und ich habe schon alles probiert :(
var fs:tfilestream; s1:string; i:integer;
begin fs:=tfilestream.Create('background.exe', fmOpenReadWrite or fmShareExclusive); try i=fs.Seek(0, soFromEnd); fs.Seek(i-4,soFromBeginning); //minus 4, weil der string 4 byte hat, und dort die andere datei auch den string ausliest. fs.Read(s1,sizeOf(s1)); showmessage(s1); finally fs.Free; Vielleicht kann mir ja einer helfen, vielen dank. mfg else_ PS: es soll später einen "builder" geben, der an die exe ein pfad von einem hintergrund hängt, und wenn man die exe ausführt, dass der hintergrund, der im builder eingestellt wurde, geändert wird.. |
Re: Filestream, string anhängen
Zitat:
MfG, Hanno |
Re: Filestream, string anhängen
Wenn du
Delphi-Quellcode:
wirst du merken, dass die Funktion nicht wirklich das macht was du erwartest...
var fs:tfilestream; s,s1:string;i:integer;
begin fs:=tfilestream.Create('C:\background.exe', fmOpenReadWrite or fmShareExclusive); try i:=fs.Seek(0, soFromEnd); s:='[test]'; fs.Write(s,sizeOf(s)); s:=''; // hier s leerst fs.Seek(i, soFromBeginning); fs.Read(s1,sizeOf(s1)); showmessage(s1); finally fs.Free; end; Strings in Delphi könnte man auch vereinfacht als Zeiger auf einen Adressbereich sehen. Du schreibst also nicht die Zeichenkette in die Datei, sondern den Zeiger darauf. MfG, Bug |
Re: Filestream, string anhängen
@hannos, nein daran lag es nicht, hatte es nur vergessen zum schluss zu editieren.. (gemacht :) )
das mit dem zeiger kann sehr gut sein, auf die idee bin ich noch gar nicht gekommen.. wie kann ich denn das ganze umgehen? mit einem byte array? damit habe ich mich noch nicht beschäftigt... |
Re: Filestream, string anhängen
Delphi-Quellcode:
alternativ
if s <> '' then
fs.Write(s[1], length(s));
Delphi-Quellcode:
alternativ
if s <> '' then
fs.Write(PChar(s)^, length(s));
Delphi-Quellcode:
if s <> '' then
fs.Write(Pointer(s)^, length(s)); |
Re: Filestream, string anhängen
Delphi-Quellcode:
habe ich probiert, sowie die anderen beispiele.. aber ich bekomme immer noch eine fehler meldung beim auslesen..
if s <> '' then
fs.Write(PChar(s)^, length(s)); fs.read
Delphi-Quellcode:
fs.Read(s1,length(s));
|
Re: Filestream, string anhängen
Hi,
hier eine Detailstudie:
Delphi-Quellcode:
Grüße vom marabu
var
fs: TFileStream; fn, s: string; begin s := 'Die Lust zu gehorchen befriedigt der Deutsche an einer roten Ampel' + sLineBreak; fn := 'c:\temp\test-stream.txt'; fs := TFileStream.Create(fn, fmCreate); fs.Write(s[1], Length(s)); s := '?'; // Length(s) = 1 fs.Free; fs := TFileStream.Create(fn, fmOpenRead); SetLength(s, fs.Size); // omit for disaster fs.Read(s[1], fs.Size); fs.Free; ShowMessage(s); end; |
Re: Filestream, string anhängen
Zitat:
Wenn das Schreiben des Strings nicht funktioniert, wenn man direkt den String angibt und einem schon zuvor gesagt wurde, dass man nur die Adresse in den Stream schreibt, dann könnte man vermuten, dass es beim auslesen wohl genauso ist. Also Maestro, das bekommste nach diesem Zaunpfahl doch bestimmt vom Lesen auf's Schreiben übertragen, oder? @marabu: das wäre dann der nächste Schritt gewesen... |
Re: Filestream, string anhängen
ah vielen dank,
ja ich bin ja auch nicht einer der direkt nachfragt.. aber im internet habe ich nur unbrauchbares gefunden, und in meinem buch (jetzt lerne ich delphi) steht es mir zu ungenau drin, und sonst habe ich nur was mit byte arrays gefunden. aber ehrlich gesagt trau ich mich nur an einen code den ich auch versteh.. und ich wusste nicht das man vor dem lesen erst den filestream wieder freigeben muss.. dankschön nochmal |
Re: Filestream, string anhängen
Zitat:
Delphi-Quellcode:
Durch fs.Free wird der Stream aber auf die Festplatte geschrieben.
begin
// ... fs.Position := 0; // fs.Free; // fs := TFileStream.Create(fn, fmOpenRead); // ... end; |
Re: Filestream, string anhängen
Hallo,
Du könntest einen der beiden TStream Nachfahren verwenden
Delphi-Quellcode:
unit Streaming;
interface uses Sysutils, Classes; Type TMemoryStreamExt = class(TMemoryStream) public procedure WriteStringToStream(aStr : String); function ReadStringFromStream : String; end; TFileStreamExt = class(TFilestream) public procedure WriteStringToStream(aStr : String); function ReadStringFromStream : String; end; implementation { TFileStreamExt } procedure TFileStreamExt.WriteStringToStream(aStr : String); var aStrLen : Integer; begin aStrLen:=Length(aStr); WriteBuffer(aStrLen,SizeOf(Integer)); WriteBuffer(Pointer(aStr)^,aStrLen); end; function TFileStreamExt.ReadStringFromStream: String; var aStrLen : Integer; begin ReadBuffer(aStrLen,SizeOf(Integer)); SetLength(Result,aStrLen); ReadBuffer(Pointer(Result)^,aStrLen); end; { TMemoryStreamExt } function TMemoryStreamExt.ReadStringFromStream: String; var aStrLen : Integer; begin ReadBuffer(aStrLen,SizeOf(Integer)); SetLength(Result,aStrLen); ReadBuffer(Pointer(Result)^,aStrLen); end; procedure TMemoryStreamExt.WriteStringToStream(aStr: String); var aStrLen : Integer; begin aStrLen:=Length(aStr); WriteBuffer(aStrLen,SizeOf(Integer)); WriteBuffer(Pointer(aStr)^,aStrLen); end; end. |
Re: Filestream, string anhängen
Zitat:
Auch wäre es recht unwahrscheinlich, das ein eben mit leer initialisierter Result(-string) sich schon den leeren Platz mit einem anderen String teilt, oder? |
Re: Filestream, string anhängen
macht SetLength das nicht nur bei Größenänderung?
[edit] ok, dachte SetLength püft vorher ob sich überhaupt was an der Länge ändert, aber *grad nachgesehn* es macht das nicht °_° Zitat:
> ![]() |
Re: Filestream, string anhängen
Ob es nun unelegant ist oder nicht, habe ich mal alles andere an Zeigern und PChar und ...
außer acht gelassen, um nochmal direkt auf den 1. Beitrag zurückzukommen.
Delphi-Quellcode:
So läuft das ganze bei mir ohne Probleme.
function GetFileStrFromEnd(FileName: String; Count: Integer): String;
var FS: TFileStream; I:integer; begin FS:=tfilestream.Create(FileName, fmOpenReadWrite or fmShareExclusive); try I:=FS.Seek(0, soFromEnd); FS.Seek(I-Count,soFromBeginning); Setlength(Result,Count); // nicht vergessen, sonst Zugriffsverletzung FS.Read(Result[1],Count); // [1] nicht vergessen, sonst Zugriffsverletzung finally fs.Free; end; end; procedure TForm1.Button1Click(Sender: TObject); begin ShowMessage( GetFileStrFromEnd('C:\background.exe', 4) ); end; MfG, Hanno |
Re: Filestream, string anhängen
Zitat:
muß ja nicht gleich negativ sein ... so knallt's auch schon genug :stupid: |
Re: Filestream, string anhängen
Klar, ich weiß, das ist die Variante, die sich eben auf den ersten Beitrag bezieht.
Aber du musst ja auch nicht Count=0 übergeben. Ich hab Count=0 mal ausprobiert, und auch ein paar negative Werte. Ergebnis ist immer nicht mehr und nicht weniger als ''. (vielleicht Zufall) Bei Count>FS.Size bekomme ich schon komische Werte heraus. Nunja, man kann den Code dahingehend noch beliebig verbessern und ausbauen, das Grundprinzip funktioniert aber bei den richtigen Count-Angaben. |
Re: Filestream, string anhängen
1. Alle TStream Nachfahren haben eine Eigenschaft
![]() 2. Warum seekst du auf eine Position 0 vom Ende aus gesehen um dann danach von vorne zu seeken? Warum seekst du nicht gleich auf Count Bytes vom Ende aus? So ist es völlige Resourcenverschwendung 3. Was macht dein Code, wenn die Datei kleiner ist als die mit Count angegebene Datengröße? Also nochmal das Ganze:
Delphi-Quellcode:
/EDIT: zweite Seite übersehen. Also wurde der 3. Punkt schon erwähnt...
function GetFileStrFromEnd(FileName: String; Count: Integer): String;
var FS: TFileStream; I:integer; begin FS:=tfilestream.Create(FileName, fmOpenReadWrite or fmShareExclusive); try if FS.Seek(Count, soFromEnd) = Count then begin Setlength(Result,Count); // nicht vergessen, sonst Zugriffsverletzung FS.Read(Result[1],Count); // [1] nicht vergessen, sonst Zugriffsverletzung end else result := ''; // stream ist kleiner finally fs.Free; end; end; |
Re: Filestream, string anhängen
Zu 2. :
Das kommt vom 1. Beitrag :angel2: . Nee, sorry, gut dass du das bemerkt hast! EDIT: hmmm, dein Code gibt bei mir immer '' aus :( . |
Re: Filestream, string anhängen
So gehts... :)
Delphi-Quellcode:
function GetFileStrFromEnd(FileName: String; Count: Integer): String;
var FS: TFileStream; I:integer; begin FS:=tfilestream.Create(FileName, fmOpenReadWrite or fmShareExclusive); try if (FS.Size>Count) and (Count>0) then begin FS.Seek(FS.Size-Count,soFromBeginning); Setlength(Result,Count); // nicht vergessen, sonst Zugriffsverletzung FS.Read(Result[1],Count); // [1] nicht vergessen, sonst Zugriffsverletzung end else begin result := ''; // stream<Count oder count<=0 end; finally fs.Free; end; end; |
Re: Filestream, string anhängen
oder mit
Delphi-Quellcode:
FS.Seek(-1*Count,soFromEnd);
|
Re: Filestream, string anhängen
Zitat:
Aber ich habe eben nochmal geschaut, Seek will trotzdem ein negativen Wert haben. Die Origin Angabe ist nur der Ausgangspunkt, bewirkt aber nichts an der Bedeutung des Offsets (ausser bei soFromBeginning, dort wird der Wert dann als unsigned interpretiert laut WinAPI). Hier dann nochmal mein korrigierter Code:
Delphi-Quellcode:
function GetFileStrFromEnd(FileName: String; Count: Integer): String;
var FS: TStream; I: integer; begin result := ''; // stream ist kleiner FS := TFileStream.Create(FileName, fmOpenReadWrite or fmShareExclusive); try if FS.Seek(-Count, soFromEnd) = FS.Size - Count then begin Setlength(Result,Count); FS.Read(Result[1],Count); end; finally fs.Free; end; end; |
Re: Filestream, string anhängen
Delphi-Quellcode:
function GetFileStrFromEnd(FileName: String): String;
var FS: TStream; I,count: integer; begin count:=0; result := ''; // stream ist kleiner FS := TFileStream.Create(FileName, fmOpenReadWrite or fmShareExclusive); try while pos('[data]',result)=0 do begin if FS.Seek(-Count, soFromEnd)=fs.Size then exit \\ noch ein fehler drin else \\ schaue morgen danach, Gute Nacht. begin if FS.Seek(-Count, soFromEnd) = FS.Size - Count then begin Setlength(Result,Count); FS.Read(Result[1],Count); end; inc(count); end; end; finally fs.Free; end; end; habe mal muetzes code angepasst.. villeicht brauch das ja jemand.. mein string fängt mit '[data]' an. und irgendwie wollte meine if anweisung kein "if not count=fs.size then..." aktzeptieren, dann habe ich es mal so gedreht ;) |
Re: Filestream, string anhängen
Delphi-Quellcode:
if not (count = fs.Size) then
//oder besser if count <> fs.Size then if count < fs.Size then
Delphi-Quellcode:
wie groß ist deine Datei, bzw. wie lang ist der String maximal, den du suchst?
function GetFileStrFromEnd(FileName: String): String;
var FS: TStream; I,count: integer; begin count:=0; result := ''; // stream ist kleiner FS := TFileStream.Create(FileName, fmOpenReadWrite or fmShareExclusive); try while (count <= fs.Size) and (pos('[data]',result) = 0) do begin if FS.Seek(-Count, soFromEnd) = FS.Size - Count then begin Setlength(Result,Count); FS.Read(Result[1],Count); end; inc(count); end; if pos('[data]',result) = 0 then result := ''; // fals string nicht gefunden wurde finally fs.Free; end; end; so ließt du ja die Datei mehrmals vom Ende her ein ... Length(Result)-mal Count=0 wurd es eh nicht geben und wenn dein String mit [data] anfängt, dann kannst bei der Vorgehensweise du auch gleich bei count=Length('[data]'); oder count=6; anfangen, den kürzer kann der String nicht sein. falls die Maximalläge nicht feststeht und du nicht immer einen genügendgroßen Block auslesen willst, dann könnte man auch in größeren Schritten zurückgehn (nicht nur 1 > inc(count), sondern gleich ein paar byte mehr oder du ließt gleich nur einmal einen größer Block (ganze Datei, oder soviel wie der String maximal lanhg ist) aus, suchst darin den Stringanfang und kopierst dir ab dem Fundort den String bis Datei-/Blockende in Result rein.
Delphi-Quellcode:
FS.Seek(-1024, soFromEnd); // 1024 = 1 KB
SetLength(Result, 1024); FS.Read(Result[1], 1024); Result := Copy(Result, Pos('[data]', Result), 1024); // statt Copy Delete(Result, 1, Pos('[data]', Result) - 1); erstellst du die Datei selber? wenn ja, dann speicher doch die Stringgröße (siehe oben), dann kannst die Auslesen und du weißt wo der String ist. Dieses Länge/Größe kann man auch nach dem String speichern (nicht immer nur davor, wie oben sichtbar)
Delphi-Quellcode:
FS.Seek(-SizeOf(Len), soFromEnd);
FS.Read(Len, SizeOf(Len)); FS.Seek(-SizeOf(Len) - Len, soFromEnd); SetLength(Result, Len); FS.Read(Result[1], Len); > alles in Kurz und ohne Fehlerprüfung und sowas |
Re: Filestream, string anhängen
das problem ist, das der string mal so mal so lang ist, und nicht konstant..
mir kommt aber gerade die idee, das der "builder" ja die zeichen länge des strings anhängen kann.. dann kann man das auslesen und die while schleife weg lassen.. die datei ist so um die 400kb groß, also um ressourcen mache ich mir nicht so große gedanken.. gute nacht :) |
Re: Filestream, string anhängen
Delphi-Quellcode:
wenn du das [data] nicht willst, dann einfach bei "i - 1" diese Länge einrechnen, also "i + 5"
function GetFileStrFromEnd(FileName: String): String;
var FS: TStream; i: integer; begin FS := TFileStream.Create(FileName, fmOpenRead or fmShareExclusive); try if FS.Size > 0 then begin FS.Position := 0; SetLength(Result, FS.Size); FS.Read(Result[1], FS.Size); i := Pos('[data]', Result); if i > 0 then Delete(Result, 1, i - 1) else Result := ''; end else Result := ''; finally FS.Free; end; end; und für die idealere Variante (siehe dem Code mit 1024 im letzten Beitrag), ... und dort einfach einen Wert wählen, der auf jeden Fall groß genug ist ^^ |
Re: Filestream, string anhängen
Ich würde bei sowas eher MMF (memory mapped filestream) verwenden, damit solltest du das viel schneller lesen, also dieses blockweise "von hinten nach vorne seeken".
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 21:24 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