Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi TFileStream: Später nochmal auf unveränderte Datei zugreifen (https://www.delphipraxis.net/98811-tfilestream-spaeter-nochmal-auf-unveraenderte-datei-zugreifen.html)

Martin K 1. Sep 2007 23:08


TFileStream: Später nochmal auf unveränderte Datei zugreifen
 
Moin,

also ich habe folgendes Problem:
Eine Datei wird zum Lesen geöffnet, etwa so:
Delphi-Quellcode:
TFileStream.Create(FileName, fmOpenRead, fmShareDenyWrite)
Also natürlich soll die Datei während dem Lesen nicht geändert werden, deswegen fmShareDenyWrite.
Nun würde ich aber nach dem Freigeben des Streams fmShareDenyWrite gerne lassen, da ich später nochmal auf die Datei zugreifen muss und diese in der Zwischenzeit nicht geändert werden sollte.
Die Frage ist:
Geht das irgendwie?

Eine andere Möglichkeit wäre natürlich, den Stream irgendwie zu Puffern und einfach im Speicher zu lassen, so dass ich beim nächsten Zugriff nicht mehr auf die Datei, sondern einfach auf den gespeicherten Stream zugriefe, doch da weiß ich irgendwie nicht, wie ich das machen soll, einfach den Stream als Variable speichern und nicht freigeben?
Was meint ihr?

Muetze1 2. Sep 2007 00:05

Re: TFileStream: Später nochmal auf unveränderte Datei zugre
 
Wenn du den Stream freigibst, dann kann jeder mit dem was machen was er will. Gib ihn nicht frei, dann bleibt er geschützt...

Martin K 2. Sep 2007 00:08

Re: TFileStream: Später nochmal auf unveränderte Datei zugre
 
Ja, das ist schon klar, aber ich brauch ihn halt einmal am Anfang und dann noch etwas später, du meinst also, dass ich den Stream dann erst ganz zum Schluss freigeben soll?

Dezipaitor 2. Sep 2007 00:50

Re: TFileStream: Später nochmal auf unveränderte Datei zugre
 
Wenn du auf die Strasse einen 1000€ Schein legst, und darauf aufpasst (mit Waffe oder so), dann wird der höchstwahrscheinlich nicht gestohlen.
Aber sobald du weggehst - wie hoch ist die Wahrscheinlichkeit, dass der Schein "Beine bekommt und wegläuft"? Richtig - sehr hoch.

Was lernen wir daraus?
Lasse nichts unbeaufsichtig, wenn du nicht willst, dass es angefasst wird. Und wenn du nicht die ganze Zeit darauf aufpassen willst, dann Sperre es weg (ACL).

Nur wo ist der Fehler?

Dax 2. Sep 2007 00:54

Re: TFileStream: Später nochmal auf unveränderte Datei zugre
 
Zitat:

Zitat von Dezipaitor
Nur wo ist der Fehler?

Es gibt keine 1000€-Scheine :mrgreen:

:duck:

Olli 2. Sep 2007 00:56

Re: TFileStream: Später nochmal auf unveränderte Datei zugre
 
Zitat:

Zitat von Dax
Zitat:

Zitat von Dezipaitor
Nur wo ist der Fehler?

Es gibt keine 1000€-Scheine :mrgreen:

:duck:

Verdammt bist du schnell :lol:

Luckie 2. Sep 2007 01:02

Re: TFileStream: Später nochmal auf unveränderte Datei zugre
 
Entweder du schliesst den FileStream nicht oder, um das ganze im Code deutlicher zu machen, übergib den FileStream einem MemoryStream. Wobei ein MemoryStreeam auch die Methode LoadFromFile kennt. Es läuft also im Prinzip beides auf das gleiche hinaus. ;)

Martin K 2. Sep 2007 01:09

Re: TFileStream: Später nochmal auf unveränderte Datei zugre
 
Also erstmal danke für eure Antworten!

Ich habe mich nun dazu entschieden, den Stream erst ganz zum Schluss freizugeben.

Es sieht folgendermaßen aus:
Am Anfang (zu Beginn meiner Prozedur) wird die Datei komplett (Byte für Byte) eingelesen.
Dann mache ich etwas und ganz zum Schluss der Prozedur wird die Datei nochmals (Byte für Byte) eingelesen.
Ich habe es jetzt so gemacht, dass der Stream über die ganze Prozedur hin geöffnet ist, und eben erst ganz zum Schluss freigegeben wird, ist denke ich auch die einfachste Methode.

Die Frage ist nur, wenn ich das in einen MemoryStream speichere, ist dann das zweite einlesen ggf. schneller?

Dax 2. Sep 2007 01:17

Re: TFileStream: Später nochmal auf unveränderte Datei zugre
 
Wenn du die Datei per LoadFromFile in einen Memorystream lädst, hast du die gesamte Datei [u]im Speicher[i]. Damit dauert das erste einlesen also um einiges länger, aber dafür sind alle anderen Operationen auf die Daten fast in Nullzeit machbar - und deine Daten werden nicht einfach so von anderen Programmen verändert, während deine Prozedur durchläuft.

Olli 2. Sep 2007 01:21

Re: TFileStream: Später nochmal auf unveränderte Datei zugre
 
Zitat:

Zitat von Dax
Wenn du die Datei per LoadFromFile in einen Memorystream lädst, hast du die gesamte Datei [u]im Speicher[i]. Damit dauert das erste einlesen also um einiges länger, aber dafür sind alle anderen Operationen auf die Daten fast in Nullzeit machbar - und deine Daten werden nicht einfach so von anderen Programmen verändert, während deine Prozedur durchläuft.

Probleme gibt es nur, wenn die Datei zu groß für den RAM und die Auslagerungsdatei ist.

Dezipaitor 2. Sep 2007 01:23

Re: TFileStream: Später nochmal auf unveränderte Datei zugre
 
Also nehmen wir mal an, dass Festplatten schneller wären als der Hauptspeicher. Was würde das bedeuten?
1. Ich hätte die Festplatten schon längst verbannt.
2. Ich hätte 2000 TB Hauptspeicher
3. Mein PC würde rund um die Uhr laufen; ich hätte Windows durch Linux ersetzt (wegen den Abstürzen); würde eine riesige Stromrechnung haben;
und nicht schlafen können, weil die Kühler so laut sind
4. Ich würde jedesmal aus dem Fenster springen (2.Stock), wenn mein PC abstürzt, weil dann alle Daten verloren sind (aktueller RAM ist noch flüchtiger Speicher)

Ja, Hauptspeicher ist (in den allermeisten Fällen) schneller als Festplattenspeicher - dafür aber kostbarer (da weniger vorhanden).
Man muss jedoch beachten, dass Wasser durch schmale Röhren länger braucht, um ans Ziel zu kommen, als durch breite Rohre.
Also lieber nicht Wass..äh Daten byteweise in den Speicher schaufeln, sondern in größeren Stücken ("Wieviel darf's denn sein?"). Dann klappts auch mit der Geschwindigkeit.

P.S.
Macht dir nichts aus dem Stil meiner Antwort - ich hab zuviel The old new thing gelesen ;-)

Martin K 2. Sep 2007 01:30

Re: TFileStream: Später nochmal auf unveränderte Datei zugre
 
o_O ich stelle grad fest, dass ist mit TMemoryStream ist nicht nur schneller, das ist viel schneller.
Danke für den Tipp :thumb:

Scheint so, dass das Einlesen Byte für Byte länger brauch, als TMemoryStream.LoadFromFile().
Z.B. bei einer 1,5 MB großen Datei hat die erste Variante schon ein paar Sekunden gedauert, mit TMemoryStream dagegen gehts so schnell, da kann man gar nicht gucken :shock:

Danke nochmals!

//Edit:
Zitat:

Zitat von Dezipaitor
sondern in größeren Stücken ("Wieviel darf's denn sein?"). Dann klappts auch mit der Geschwindigkeit.

Ja, das ist die Frage - wie groß sind die Stücke im Idelfall?
Also bei meinem Beispiel einer 1,5 MB großen Datei dürfte das bei 1 GB RAM kein Problem sein, oder?
Wobei das natürlich bei Dateien jeder beliebigen Größe optimal gehen sollte...

Dax 2. Sep 2007 01:48

Re: TFileStream: Später nochmal auf unveränderte Datei zugre
 
Wenn deine Prozedur die Datei byteweise einliest und verarbeitet, mach do sowas:
Delphi-Quellcode:
var
  fs: TFileStream;
  buffer: array[0..32767] of Byte;
  byteCount, i: Integer;
begin
  fs := ... ;
  repeat
    byteCount := fs.Read(buffer, sizeof(buffer));
    for i := 0 to byteCount do
      verarbeite buffer[i];
    until byteCount = 0;
end;
Damit dürfte immer alles recht fix gehen, bei minimaler Speicherbelastung.

Martin K 2. Sep 2007 02:02

Re: TFileStream: Später nochmal auf unveränderte Datei zugre
 
OK, das sieht ganz gut aus, für die 32767 dann am besten eine Konstante nehmen, so kann man es leicht ändern.
Kleiner Schönheitsfehler: In der For-Schleife muss es byteCount-1 heißen.

Könnte man das Ermitteln von sizeof(buffer) nicht auch durch das Verwenden einer Konstante performanter machen?

Ist jetzt vielleicht ein wenig OT, aber ich muss die Datei eigentlich Bitweise lesen, aber der Buffer geht nicht zufällig auch mit einem array of Boolean?
Ich habe es halt bisher so gemacht, dass ich das eingelesene Byte in einer weiteren For-Schleife jeweils um i nach rechts Shifte und dann eben mit and 1 ...

Dax 2. Sep 2007 02:07

Re: TFileStream: Später nochmal auf unveränderte Datei zugre
 
Zitat:

Zitat von Martin K
Kleiner Schönheitsfehler: In der For-Schleife muss es byteCount-1 heißen.

In der Tat.. Entschuldige ;)


Zitat:

Zitat von Martin K
Könnte man das Ermitteln von sizeof(buffer) nicht auch durch das Verwenden einer Konstante performanter machen?

sizeof ist Compilermagic, das wäre also unnötig.


Zitat:

Zitat von Martin K
Ist jetzt vielleicht ein wenig OT, aber ich muss die Datei eigentlich Bitweise lesen, aber der Buffer geht nicht zufällig auch mit einem array of Boolean?
Ich habe es halt bisher so gemacht, dass ich das eingelesene Byte in einer weiteren For-Schleife jeweils um i nach rechts Shifte und dann eben mit and 1 ...

Nöp, das geht nicht. Du musst wohl mit der Schleife leben.

Martin K 2. Sep 2007 02:12

Re: TFileStream: Später nochmal auf unveränderte Datei zugre
 
Gut, danke nochmal an alle, werde das dann mal soweit umsetzen.
:-D

Olli 2. Sep 2007 03:10

Re: TFileStream: Später nochmal auf unveränderte Datei zugre
 
Wenn du unterhalb von (RAM+Auslagerungsdatei)-Größe bleibst, sollte es keine Probleme geben. Allerdings solltest du beachten, daß andere Anwendungen laufen und das OS selber auch RAM braucht - zieh also noch einen großen Brocken davon ab und dur bist immer auf der sicheren Seite. Ab Windows 2000 solltest du bspw. ohne weiteres 64 MiB laden können. Soweit ich weiß benutzt das ja auch MMFs und wenn die Implementierung korrekt ist, wird sich der Memory-Manager drum kümmern, daß die Daten im Speicher verfügbar sind (wobei Speicher nicht gleichzusetzen ist mir phys. RAM - schließlich reden wir über Usermode) ;)

Dezipaitor 2. Sep 2007 12:51

Re: TFileStream: Später nochmal auf unveränderte Datei zugre
 
Zitat:

Zitat von Martin K
Ist jetzt vielleicht ein wenig OT, aber ich muss die Datei eigentlich Bitweise lesen, aber der Buffer geht nicht zufällig auch mit einem array of Boolean?
Ich habe es halt bisher so gemacht, dass ich das eingelesene Byte in einer weiteren For-Schleife jeweils um i nach rechts Shifte und dann eben mit and 1 ...

In der grauen Vorzeit hat man sich geeinigt, dass Computer Bytestreams verarbeiten und nicht Bitstreams. Es gab damals ja auch noch die Lochkarten,
welche Bits darstellten. Aber schon damals hat man mehrere Bits zusammengefasst.

Die Frage kommt sehr oft im Forum.

Martin K 2. Sep 2007 15:04

Re: TFileStream: Später nochmal auf unveränderte Datei zugre
 
Danke nochmals für eure Antworten :)

Zitat:

Zitat von Olli
Soweit ich weiß benutzt das ja auch MMFs und wenn die Implementierung korrekt ist, wird sich der Memory-Manager drum kümmern, daß die Daten im Speicher verfügbar sind

Kannst du das mal genauer erklären?
Was ist MMF?

Ich habe irgendwie immernoch folgendes Problem:
Für kleinere Textdateien ist die von Dax vorgeschlagene Buffergröße von 32 KB vielleicht ganz gut, aber wenn ich eine mehrere MB große Datei habe, wäre eine Buffergröße von 64 MB nicht schlecht (wie Olli sagt, dürfte das kein Problem sein).
Allerdings wenn ich dann bei dem 64 MB großen Buffer nur eine kleine Textdatei einlese mit ein paar KB, dann belege ich ja trotzdem die 64 MB im Speicher -> nicht so optimal.
Was empfehlt ihr?
Vielleicht doch wieder TMemoryStream verwenden?

Olli 2. Sep 2007 15:08

Re: TFileStream: Später nochmal auf unveränderte Datei zugre
 
Zitat:

Zitat von Martin K
Was ist MMF?

Memory Mapped Files

Zitat:

Zitat von Martin K
Vielleicht doch wieder TMemoryStream verwenden?

Ja

FAlter 2. Sep 2007 15:11

Re: TFileStream: Später nochmal auf unveränderte Datei zugre
 
Hi,

auch, wenn es nicht das eigentliche Problem betrifft, jedoch:

Zitat:

Zitat von Martin K
Eine Datei wird zum Lesen geöffnet, etwa so:
Delphi-Quellcode:
TFileStream.Create(FileName, fmOpenRead, fmShareDenyWrite)
Also natürlich soll die Datei während dem Lesen nicht geändert werden, deswegen fmShareDenyWrite.

Das muss richtig heißen:
Delphi-Quellcode:
TFileStream.Create(FileName, fmOpenRead or fmShareDenyWrite)
Zumindest sagt meine OH, dass der zweite Parameter nur unter Linux funktioniert und für die Rechte steht (womit aber das gemeint ist, was sich per chmod ändern lässt). Unter Windows wird er ignoriert.

Mfg
FAlter

Martin K 2. Sep 2007 15:14

Re: TFileStream: Später nochmal auf unveränderte Datei zugre
 
Zitat:

Zitat von Olli
Zitat:

Zitat von Martin K
Was ist MMF?

Memory Mapped Files

Zitat:

Zitat von Martin K
Vielleicht doch wieder TMemoryStream verwenden?

Ja

Oh, das war aber ne kurze Erklärung :stupid:

Also angenommen ich lade eine 4 GB große Datei in einen TMemoryStream und habe einen RAM von 1 GB.
Passt das dann noch irgendwie in die Auslagerungsdatei (wobei andere Anwendungen ja auch noch RAM verbrauchen), oder was macht TMemoryStream dann?
Gibts dann ne Exception, wenn das zu groß wird für einen MemoryStream?

Olli 2. Sep 2007 15:19

Re: TFileStream: Später nochmal auf unveränderte Datei zugre
 
Zitat:

Zitat von Martin K
Also angenommen ich lade eine 4 GB große Datei in einen TMemoryStream und habe einen RAM von 1 GB.
Passt das dann noch irgendwie in die Auslagerungsdatei (wobei andere Anwendungen ja auch noch RAM verbrauchen), oder was macht TMemoryStream dann?
Gibts dann ne Exception, wenn das zu groß wird für einen MemoryStream?

Weiß nicht wie der das handhabt. Aber man kann auch bestimmte Abschnitte einer MMF anfordern. Wenn es also gut gekapselt ist, sollte es kein Problem sein.

Relevant ist, wie gesagt, die Größe des RAMs und der Auslagerungsdatei zusammen, minus das was vom OS selber und anderen Anwendungen gebraucht wird.

Martin K 2. Sep 2007 15:24

Re: TFileStream: Später nochmal auf unveränderte Datei zugre
 
Zitat:

Zitat von Olli
Relevant ist, wie gesagt, die Größe des RAMs und der Auslagerungsdatei zusammen, minus das was vom OS selber und anderen Anwendungen gebraucht wird.

Ja, das ist schon klar, aber das ist eben die Frage, ob das bei (sehr) großen Dateien nicht ein wenig end wird und was dann passiert...

@FAlter: also ehrlich gesagt bin ich da überfragt :pale:
Aber ich seh auch grad, dass in der Hilfe steht, dass man es mit or verknüpfen soll.
Wobei es bei TFileStream diese beiden Konstruktoren gibt :gruebel:
Delphi-Quellcode:
constructor Create(const AFileName: string; Mode: Word); overload;
constructor Create(const AFileName: string; Mode: Word; Rights: Cardinal); overload;


Alle Zeitangaben in WEZ +1. Es ist jetzt 17:15 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