Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Sonstige Fragen zu Delphi (https://www.delphipraxis.net/19-sonstige-fragen-zu-delphi/)
-   -   FileToString: Wie String zu "StringToFile?" (https://www.delphipraxis.net/77900-filetostring-wie-string-zu-stringtofile.html)

Go2EITS 26. Sep 2006 15:47


FileToString: Wie String zu "StringToFile?"
 
Hallo DP,
Der Code aus der DP funktioniert ganz gut.
Aber mit den StringToFile stehe ich auf dem Kriegsfuss.
Für mein Tool, dass ich der DP Delphi Cleaner zur Verfügung gestellt habe, läuft die CopyDir wahrscheinlich zu langsam. Daher habe ich alle Files schon beim Suchen über FiletoString eingelesen. Nun bauche ich alle Strings wieder als File... Nur wie?

Hier der funktionierende Code aus der DP:

Delphi-Quellcode:
function FileToString(const FileName: string): AnsiString;
var
  fs: TFileStream;
  Len: Integer;
begin
  fs := TFileStream.Create(FileName, fmOpenRead or fmShareDenyWrite);
  try
    Len := fs.Size;
    SetLength(Result, Len);
    if Len > 0 then
      fs.ReadBuffer(Result[1], Len);
  finally
    fs.Free;
  end;
end;
Könnt Ihr mir wieder mal weiterhelfen? :thumb:
Beste Grüße
Go2EITS

mkinzler 26. Sep 2006 15:49

Re: FileToString: Wie String zu "StringToFile?"
 
Schon mal mit .WriteBuffer versucht?

Go2EITS 26. Sep 2006 16:01

Re: FileToString: Wie String zu "StringToFile?"
 
Hallo, mkinzler, nett dass Du bei mir reinsiehst.

Ähm, das ist ja das Problem.
Tstream.read und write habe ich mir schon im Tutorial der dsdt.de angesehen.
Wie setzte ich denn den Code oben um? Wäre ja nicht nur für mich interessant.
Also ich habe mal jetz so angefangen. Natürlich könnte ich wohl eine Fehlermeldung zurückgeben,
wenn der Stream nicht korrekt geschreiben wurde.

Delphi-Quellcode:
Procedure StringToFile(VAR FileName, Str: string);
var
  fs: TFileStream;
  Len: Integer;
begin
  fs := TFileStream.Create(FileName, fmOpenRead or fmShareDenyWrite);
  try
    Len := fs.Size;
    SetLength(Result, Len);
    if Len > 0 then
      fs.WriteBuffer(Result[1], Len);
  finally
    fs.Free;
  end;
end;
So funktioniert es ja nicht. Das Result ist ein Schmarren, weil ich ja eine Procedure habe.
Magst Du den Code mal verbessern?
:pale:

Neutral General 26. Sep 2006 16:03

Re: FileToString: Wie String zu "StringToFile?"
 
Delphi-Quellcode:
Procedure StringToFile(VAR FileName, Str: string);
var
  fs: TFileStream;
  Len: Integer;
begin
  fs := TFileStream.Create(FileName, fmOpenRead or fmShareDenyWrite);
  try
    Len := Length(Str);
    fs.Write(Len, SizeOf(Integer));
    fs.Write(Str[1], Len);
  finally
    fs.Free;
  end;
end;
so müsstes gehn :)

Gruß
Neutral General

Leonard 26. Sep 2006 16:11

Re: FileToString: Wie String zu "StringToFile?"
 
Hallo,

seid ihr sicher, dass das stimmt :?:
Delphi-Quellcode:
fs := TFileStream.Create(FileName, fmOpenRead or fmShareDenyWrite);
Ich denke wenn man in den Stream reinschreiben möchte sollte man ihm das auch sagen :)

Delphi-Quellcode:
fs := TFileStream.Create(FileName, fmCreate);
mfg Leonard

Go2EITS 26. Sep 2006 16:21

Re: FileToString: Wie String zu "StringToFile?"
 
Ich habe gerade noch über den Code gegrübelt und den Vorschlag von mkinzler zum laufen gebracht. Ich probiere das gerade mal:

Delphi-Quellcode:
Procedure StringToFile(VAR FileName, Str: string);
var
  fs: TFileStream;
  Len: Integer;
begin
  fs := TFileStream.Create(FileName, fmCreate);
  try
    Len := fs.Size;
    SetLength(str, Len);
    if Len > 0 then
      fs.WriteBuffer(str[1], Len);
  finally
    fs.Free;
  end;
end;
Ich habe keine Ahnung, ob es Wirklich geht. Mein Tool braucht mit CopyDir zu lange. Es wird noch dauern, bis ich weiss, ob und was letztendlich zuverlässig funzt... falls nicht, probiere ich Deinen Vorschlag, Neural general! Dankeschön schon mal vorab aun Euch [roter Kasten ] drei! Auf writebuffer wäre ich nicht gekommen. :thumb:

Roter Kasten!
Oha, Leonhard, ichglaube Du hast recht! Ändere ich gleich oben noch.

marabu 26. Sep 2006 16:22

Re: FileToString: Wie String zu "StringToFile?"
 
Hallo,

ich kann zwar keinen Sinn darin erkennen den Inhalt einer beliebigen Datei (binär?, riesig?) als String im Hauptspeicher zu lagern, aber wenn überhaupt, dann würde ich einen MemoryStream als Zwischenlager benutzen. Die Größe der ursprünglichen Datei darf natürlich nicht geschrieben werden, da so der Dateiinhalt verändert wird:

Delphi-Quellcode:
procedure LoadStream(s: TStream; fn: TFileName);
var
  fs: TFileStream;
begin
  fs := TFileStream.Create(fn, fmOpenRead or fmShareDenyWrite);
  try
    s.CopyFrom(fs, fs.Size);
    s.Position := 0;
  finally
    fs.Free;
  end;
end;

procedure SaveStream(s: TStream; fn: TFileName);
begin
  with TFileStream.Create(fn, fmCreate) do
  try
    s.Position := 0;
    CopyFrom(s, s.Size);
  finally
    Free;
  end;
end;
Getippt und nicht getestet.

Freundliche Grüße vom marabu

Go2EITS 26. Sep 2006 16:47

Re: FileToString: Wie String zu "StringToFile?"
 
@marabu

Na nun kann ich mich garnicht entscheiden...
Es sind 951 Files mit insgesamt 1,79 MB. Alles überflüssige Dateien.
Die lese ich gerade in eine Stringlist ein. Und nun statt 10 Minuten Backup mit Copydir, 10 Sekunden. Alles ist angelegt, aber die Files sind 0-Bytes. Mein Codde geht also nicht. War auch ein wenig zu schnell..

Ich probiere den Code von Neutral General aus. Natürlich mit der Änderung von Leonhard.
Ca. 15 Sekunden! Ich sehe nach und 951 Files, 1,79 MB und 406 sind im Backupordner. Suuuuper!
Ich hatte die Daten aber schon beim Suchen der betreffenden Files wegen der Performance in eine Stringlist eingelesen. Aber bei 1,91 MB.

So der Zwischenstand. Ich probiere mal den Code von marabu auch aus. Der ist wohl für größere Dateien geeignet. Und dann gibt es nachher gleich ein Update von dem Tool Delhi Cleaner,Delphi Cleaner Dank Eurer Hilfe!
Ihr dürft es gerne mal ansehen. Lasst Euch mal überraschen, wie viele entbehrliche Dateien Eure Festplatten belegen.

Bis später... und vielen Dank! :thumb: :thumb: :thumb:

Go2EITS 26. Sep 2006 19:02

Re: FileToString: Wie String zu "StringToFile?"
 
@Marabu
Mit den Streams scheitere ich leider schon bei den Übergabeparametern. Dein Code sieht aber interessant aus. Da benötige ich mehr LernZeit um ein Stream zu erstellen, damit ich den als Parameter Deinen Proceduren übergeben kann. Dies ist aber nicht allein das Problem. Es stellt sich ja die Frage der Weiterverarbeitung bzw. Zugriff der Daten.

Aber das Problem ist ja gelöst: Hier nochmals der vollständige richtige Code, den ich verwendet habe, weil viele Threads oft die richtige Lösungen leider offen lassen, dass neue Thread notwendig werden. Daher der funktionierende und vollständige Code nachfolgend:

FileToString:

Delphi-Quellcode:
function FileToString(const FileName: string): AnsiString;// inline;
var
  fs: TFileStream;
  Len: Integer;
begin
  fs := TFileStream.Create(FileName, fmOpenRead or fmShareDenyWrite);
  try
    Len := fs.Size;
    SetLength(Result, Len);
    if Len > 0 then
      fs.ReadBuffer(Result[1], Len);
  finally
    fs.Free;
  end;
end;
Und wieder zurück mit StringToFile

Delphi-Quellcode:
Procedure StringToFile(const FileName, Str: string);//Inline;
var
  fs: TFileStream;
  Len: Integer;
begin
  fs := TFileStream.Create(FileName, fmcreate);
  try
    Len := Length(Str);
    fs.Write(Len, SizeOf(Integer));
    fs.Write(Str[1], Len);
  finally
    fs.Free;
  end;
end;
EDIT: Nachträglich var in Const geändert, lt. marabu
Betraf ursprünglichen Code: Procedure StringToFile(VAR FileName, Str: string);//Inline;

Inline verwende ich unter Turbo2006.
Viel Vergnügen und beste Grüße.
Go2EITS

marabu 27. Sep 2006 06:32

Re: FileToString: Wie String zu "StringToFile?"
 
Guten Morgen.

Zitat:

Hier nochmals der vollständige richtige Code
Sicher kannst du dir nur sein, wenn du die Funktionen auch richtig getestet hast. Es soll ja folgendes gelten:

Delphi-Quellcode:
var
  s: String;
  fn: TFileName;
begin
  fn := ChangeFileExt(ParamStr(0), '.tmp');
  s := FileToString(ParamStr(0));
  StringToFile(fn, s);
  if FileToString(fn) = s
    then ShowMessage('passed')
    else ShowMessage('failed');
end;

// procedure StringToFile(const FileName, Str: String);
Die Parameter der Prozedur StringToFile() solltest du besser als Konstanten übergeben. Ein Blick mit dem Windows Explorer auf das Dateisystem sollte dir offenbaren, dass die beiden Dateien aus meiner Testroutine einen Größenunterschied von 4 Byte aufweisen.

Zitat:

Zitat von marabu
Die Größe der ursprünglichen Datei darf natürlich nicht geschrieben werden, da so der Dateiinhalt verändert wird:

Grüße vom marabu

Go2EITS 27. Sep 2006 18:56

Re: FileToString: Wie String zu "StringToFile?"
 
@marabu
Vielen Dank für Deine Antwort, meine Routinen kopieren exakt.
Die Files sind im Original und als Backup unverändert.

Const funtioniert. Warum soll ich ein Const nehmem. Für mich ungewohnt...

marabu 27. Sep 2006 19:19

Re: FileToString: Wie String zu "StringToFile?"
 
Mein letzter Versuch: du schreibst in Zeile 9 der Prozedur StringToFile() aus deinem Beitrag #9 eine Längeninformation in die Datei, welche beim Einlesen noch nicht vorhanden ist. Dadurch haben die gelesene Datei und die geschriebene Datei nicht mehr den gleichen Inhalt. Bin ich denn der einzige hier, der das sieht?

Das Schlüsselwort CONST in der Signatur von StringToFile() dokumentiert für den kundigen Leser, dass die Argumente der Prozedur garantiert nicht inhaltlich verändert werden. In Verbindung mit dem Datentyp String erlaubt diese Vorgehensweise dem Compiler gewisse Optimierungsmaßnahmen zu ergreifen.

Grüße vom marabu

Go2EITS 27. Sep 2006 19:55

Re: FileToString: Wie String zu "StringToFile?"
 
Ok, auch in der Gefahr dass ich es nicht verstanden habe, damit können wir aber beide gut Leben, marabu.

Du meinst eine Datei, die wohl offen ist, bzw. während des Schreibens sich verändert.
Dann kann der geschreibene Stream nicht stimmen. Klar. Aber das Problem kenne ich.
Eine FileInUse lösch das Problem auch nicht. Nur ein Backup via Linux/BartCD. Aber in meinem Falle wäre es mit Spatzen auf Kanonen, sorry, anders rum, schießen. OK?
Zitat:

Das Schlüsselwort CONST in der Signatur von StringToFile() dokumentiert für den kundigen Leser, dass die Argumente der Prozedur garantiert nicht inhaltlich verändert werden. In Verbindung mit dem Datentyp String erlaubt diese Vorgehensweise dem Compiler gewisse Optimierungsmaßnahmen zu ergreifen.
An Klarheit und Exaktheit eine hervorrangende Erklärung! TOP!

Danke für Deine Mühe, marabu!
Go2EITS

Leonard 27. Sep 2006 20:19

Re: FileToString: Wie String zu "StringToFile?"
 
Zitat:

Zitat von marabu
Mein letzter Versuch: du schreibst in Zeile 9 der Prozedur StringToFile() aus deinem Beitrag #9 eine Längeninformation in die Datei, welche beim Einlesen noch nicht vorhanden ist. Dadurch haben die gelesene Datei und die geschriebene Datei nicht mehr den gleichen Inhalt. Bin ich denn der einzige hier, der das sieht?

Auf die Frage hin hab ich mir die Prozedur auch nocheinmal angeschaut. Stimmt, hast Recht. So wie es da steht wird vor dem übergebenen Str die Länge dessen geschrieben. Das die Dateien auf diese Art und Weise danach wirklich gleich sind kann ich auch nicht glauben. Habs aber ehrlich gesagt selber nicht probiert. Also marabu, musst nicht an dir zweifeln :-D
Schönen Abend noch... Leonard

Go2EITS 29. Sep 2006 10:59

Re: FileToString: Wie String zu "StringToFile?"
 
Neues Problem:
Der Code Filetostring und Stringtofile scheint die gelesen Daten auf der Festplatte noch offen zu haben; das Löschen geht nur, wenn mein Programm, das die Daten eingelesen hat, geschlossen wird. Gibt es ein Close dazu? Ich habe bei den Streams nachgesehen, konnte aber nichts finden.

@marabu
Ich habe mir den Code auch angesehen: Der Code schreibt in die Backups die Länge an den Anfang. :pale: Ich kann obigen Code nicht mehr ändern:
Also den Code verwenden:
Delphi-Quellcode:
function FileToString(const FileName: string): AnsiString;// inline;
var
  fs: TFileStream;
  Len: Integer;
begin
  fs := TFileStream.Create(FileName, fmOpenRead or fmShareDenyWrite);
  try
    Len := fs.Size;
    SetLength(Result, Len);
    if Len > 0 then
      fs.ReadBuffer(Result[1], Len);
  finally
    fs.Free;
  end;
end;

Procedure StringToFile(const FileName, Str: string);//Inline;
var
  fs: TFileStream;
  Len: Integer;
begin
  fs := TFileStream.Create(FileName, fmcreate);
  try
    Len := Length(Str);
    // fs.Write(Len, SizeOf(Integer)); Raus damit!!!!!!
    fs.Write(Str[1], Len);
  finally
    fs.Free;
  end;
end;
Vielen Dank Marabu, Dein Einwand war absolut berechtigt! :thumb:


Gruß
Go2EITS

Go2EITS 1. Okt 2006 08:19

Re: FileToString: Wie String zu "StringToFile?"
 
Guten Morgen DP!
Das Problem besteht noch:
Zitat:

Der Code Filetostring und Stringtofile scheint die gelesen Daten auf der Festplatte noch offen zu haben; das Löschen geht nur, wenn mein Programm, das die Daten eingelesen hat, geschlossen wird. Gibt es ein Close dazu? Ich habe bei den Streams nachgesehen, konnte aber nichts finden.
Ich habe in der Hilfe nochmals nachgesehen: Ein FileClose soll helfen. Ich habe daher, wie "beschrieben" (ohne weiteren Hinweis oder ein Beispiel), nach dem fs.free in der StringtoFile ein Fileclose(fs.handle); eingefügt:
Delphi-Quellcode:

Procedure StringToFile(const FileName, Str: string);//Inline;
var
  fs: TFileStream;
  Len: Integer;
begin
  fs := TFileStream.Create(FileName, fmcreate);
  try
    Len := Length(Str);
    fs.Write(Str[1], Len);
  finally
    fs.Free;
    Fileclose(fs.handle); //Das funzt net! 
end;
end;
Das bringt mir eine Exception. :gruebel:
Kann es sein, dass ich beim Lesen z. B. von 900 Files hintereinander mit "FileToString" auch alle Handles holen muss und daher nur ein, nämlich das letzte Handle, schließe?
Oder kann es sein, dass ich das Handle beim Lesen noch offen habe? Wie gesagt: Streams sind für mich Neuland.

Hat da jemand einen Ansatz zur Lösung? :gruebel:
Vielen Dank für Eure Mühe (Mit der Lösung kommt dann auch Delphi Clean 1.2 Beta ohne dem Beta für Euch raus! :zwinker:
Beste Grüße
Go2EITS

marabu 1. Okt 2006 09:41

Re: FileToString: Wie String zu "StringToFile?"
 
Guten Morgen.

Du musst an einer anderen Stelle suchen - der Destruktor von TStream gibt das file handle frei.

Grüße vom marabu

Go2EITS 1. Okt 2006 10:14

Re: FileToString: Wie String zu "StringToFile?"
 
Guten Morgen marabu,

es kann sein, dass dies (mit dem Handle) der Fehler nicht ist? Im Internet finde ich nirgends ein Fileclose in Verbindung zu den Stream Beispielen. Die Aktionen werden im Regelfall mit Free geschlossen/beendet . Da sich sonst niemand meldet, scheint das Problem mit dem Handle wohl nicht die Ursache und auch ein Fileclose nocht notwendig zu sein.

Vielleicht ist ja Deletefile(Filename) der Verursacher und nicht die Streams. Ich kann mir daher keinen Reim machen, wieso die Verzeichnisse via Explorer nicht löschbar sind, wenn mein Programm noch offen ist, aber alle Aktionen korrekt ausgeführt hat. Ich greife auf diese Quellverzeichnisse nur mit StringtoFile und Deletefile darauf zu. :gruebel:

Beste Grüße
Go2EITS

Hawkeye219 1. Okt 2006 10:28

Re: FileToString: Wie String zu "StringToFile?"
 
Hallo Go2EITS,

hast du vielleicht in deinem Code ein "FindFirst" ohne abschließendes "FindClose" benutzt? Das könnte eine Erklärung für die Fehlermeldung des Explorers sein.

Gruß Hawkeye

marabu 1. Okt 2006 11:51

Re: FileToString: Wie String zu "StringToFile?"
 
HAllo,

noch eine Hilfe zur Selbsthilfe: Der Process Explorer von SysInternals zeigt, wenn man die eigene Anwendung selektiert, welche Resourcen (noch) zugeordnet sind. Zusammen mit dem integrierten Debugger der Delphi IDE sollte es ein Leichtes sein, die fehlerhaften Code-Strecken zu identifizieren.

Grüße vom marabu

Go2EITS 2. Okt 2006 12:32

Re: FileToString: Wie String zu "StringToFile?"
 
@marabu
Der Prozessexplorer und der Fileexplorer halfen mir nicht weiter.
@Hawkeye219
Da könnte etwas dran sein, weil ich die Schleife vorzeitig verlasse und FindClose wohl nicht mehr aufgerufen wird. Das sehe ich mir mal genauer die Woche an. dazu muss ich mir erst mal einen Testcode "basteln" und etwas Zeit finden.

Danke für Eure Hilfe. Ich vermute das FindClose könnte es sein.
Ich melde, was es war. Vielen Dank vorerst! :thumb:

Beste Grüße
Go2EITS

QuickAndDirty 2. Okt 2006 13:01

Re: FileToString: Wie String zu "StringToFile?"
 
Wenn es sich nur um das kopieren dreht,
Was würde gegen ShellExecute aus der unit shellapi und dem Systemprogramm xcopy sprechen ?

OffTopic:
Das hätte auch den Vorteil das man geöffnete Dateien Kopieren kann...xcopy und ein komandozeilen Zipper ist da Leistungsfähiger
als manch eine Bezahldatensicherung...

Go2EITS 2. Okt 2006 14:43

Re: FileToString: Wie String zu "StringToFile?"
 
@Schnellundschmutzig
Auch eine Idee. Danke. :thumb:
Go2EITS

QuickAndDirty 4. Okt 2006 00:41

Re: FileToString: Wie String zu "StringToFile?"
 
der name ist halt programm...

RolfPolf 24. Aug 2007 10:01

Re: FileToString: Wie String zu "StringToFile?"
 
Hallo,
schon klar dass dieser Thread fast ein Jahr alt ist, aber wenn jemand nach StringToFile sucht landet er schnell hier und hat dann fehlerhaften Code ohne eine Lösung.
Deshalb hier kurz das obige Problem:
Zitat:

Zitat von Go2EITS
Delphi-Quellcode:
  finally
    fs.Free;
    Fileclose(fs.handle); //Das funzt net! 
  end;

Das kann ja nicht funktionieren. Erst wird mit Free das Objekt samt zugehörigem Speicher freigegeben, dann wird versucht auf das Handle des Objekts welches es gar nicht mehr gibt zuzugreifen um es zu schließen.

Der Rolf

DP-Maintenance 24. Aug 2007 11:13

DP-Maintenance
 
Dieses Thema wurde von "Matze" von "Programmieren allgemein" nach "Sonstige Fragen zu Delphi" verschoben.
Delphi-Frage


Alle Zeitangaben in WEZ +1. Es ist jetzt 02:14 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz