![]() |
Datei lesen auf "einmal"
Ich möchte eine Datei "auf einmal" einlesen. So in etwa:
Delphi-Quellcode:
var FilePointer:Pointer;
begin FilePointer := LoadFileAufEinmal( FileName:string ); |
Re: Datei lesen auf "einmal"
???
Ich versteh nicht was du willst, lege dir aber mal einen TMemoryStream oder ein TFileStream nahe^^ mfG Markus |
Re: Datei lesen auf "einmal"
Das ganze binäre Inhalt einer Datei von HD zur RAM und ein Pointer auf den Anfang.
|
Re: Datei lesen auf "einmal"
nimm einfach einen TMemoryStream und verwende die Methode LoadFromStream. Der Memorystream müsste dann noch ein property "memory" (oder so ähnlich) haben womit du einen pointer auf die Daten bekommst.
|
Re: Datei lesen auf "einmal"
Zonk!!!
Der TMemoryStream muss mit LoadFromfile gefüllt werden!!! Ansonsten kann man schon ganz bequem auf die einzelnen Werte zugreifen ... read & readBuffer! Oder du nimmst deinen Pointer, der unter Memory zu finden ist. mfG Markus |
Re: Datei lesen auf "einmal"
Zitat:
Das macht man mit FileOpen, dann mit FileSeek die Groesse der Datei holen, dann einen Speicherplatz mit GetMem (über den gewünschten pointer) reservieren und zum Schluss noch mit FileRead die Datei "AufEinmal" einlesen....... |
Re: Datei lesen auf "einmal"
Zitat:
warum? Also ich hab erst vorhin LoadFromStream verwendet und wüßte jetzt nicht warum ich LoadFromFile hätte verwenden sollen. Der Sinn von Streams ist es gerade, dass sie durchaus von dem konkreten Speicherort (RAM, File, kommt aus dem Netz) abstrahieren können. Sollte es doch ein guten Grund geben nur LoadFromFile zu nehmen, müsste ich wohl einigen Kunden etwas erklären (also hoffe ich doch mal dass es den auch weiterhin nicht gibt!) Gruß Der Unwissende |
Re: Datei lesen auf "einmal"
Zumal .LoadFromFile nix anderes tut als nen FileStream zu erstellen und den ganzen Inhalt der Datei in den Speicher zu kopieren^^
|
Re: Datei lesen auf "einmal"
In einem Rutsch in einen String laden:
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; |
Re: Datei lesen auf "einmal"
@Der_Unwissende: Naja, irgendwie muss man ja die Datei in der Speicher holen, oder ?? ;)
|
Re: Datei lesen auf "einmal"
ich habe es inzwischen so gemacht:
Delphi-Quellcode:
TByteArray = array of Byte;
function S_win_ReadFile(const FileName: string; var Data: Pointer): Cardinal; var FileHandle, BytesRead: Cardinal; begin FileHandle := CreateFile(PChar(FileName), GENERIC_READ, 0, nil, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0); if FileHandle = INVALID_HANDLE_VALUE then begin Result := 0; Data := nil; Exit; end; Result := GetFileSize(FileHandle, nil); GetMem(Data, Result); ReadFile(FileHandle, Data^, Result, BytesRead, nil); CloseHandle(FileHandle); end; function S_pascal_ReadFile(const FileName: string; var Data: TByteArray): Cardinal; var FileHandle: file; BytesRead: Cardinal; begin {$I-} AssignFile(FileHandle, FileName); Reset(FileHandle, 1); Result := FileSize(FileHandle); SetLength(Data, Result); BlockRead(FileHandle, Data[0], Result, BytesRead); CloseFile(FileHandle); {$I+} end; |
Re: Datei lesen auf "einmal"
Ich hab mal noch 2 Möglichkeiten (habe beide schnell hergeleitet, die Theorie sollte stimmen, evtl. Tippfehler ausbessern ;-)
1. Möglichkeit, mit einem Pointer:
Delphi-Quellcode:
2. Möglichkeit mit nem TMemoryStream, hier bin ich mir ne so sicher, ob das alles so richtig oder wichtig ist ;) :
procedure LoadFromFileComplete(const FN: TFileName);
var Datei: Pointer; //sollte jenachdem ob du ihn in anderen functions und procedures brauchst evtl. global sein FS: TFileStream; begin FS := TFileStream.Create(FN, fmOpenRead); try GetMem(Datei, FS.Size); //reserviert Speicher, der mit FreeMem() wieder freigegeben werden muss! FS.ReadBuffer(Datei, FS.Size); finally FS.Free; end; end;
Delphi-Quellcode:
Aber die obere Methode sollte gehn!
procedure LoadFromFileComplete(const FN: TFileName);
var Datei: TMemoryStream;//sollte jenachdem ob du ihn in anderen functions und procedures brauchst evtl. global sein //dann muss natürlich das Erzeugen und das Freigeben auch im OnCreate und im OnDestroy oder so passieren FS: TFileSream; begin FS := TFileStream.Create(FN, fmOpenRead); try Datei := TMemoryStream.Create; try Datei.SetSize(FS.Size);//die zwei zeilen sind evtl. überflüssig Datei.Seek(0, soFromBeginning);// || Datei.CopyFrom(FS, 0);//0 sollte für alles stehen //wenn du darauf jetzt noch nen Pointer brauchst musst du dir einen deklarieren und mit Datei.Memory gleichsetzen finally Datei.Free; end; finally FS.Free; end; end; PS: Solltest du mal große Dateien mit Streams bearbeiten bergiss nicht den Int64 statt nem Integer zu nehmen wenn du Längenangaben liest! |
Re: Datei lesen auf "einmal"
Meine Variante hat gegenüber den letzten 2 Varianten vier entscheidende Vorteile:
1.) durch die Verwendung von AnsiString entfällt für den Aufrufer die Pflicht den Speicher freizugeben 2.) durch die Verwendung von AnsiString kann der Aufrufer ganz leicht die Länge der Daten mit Lenght() ermitteln. Man braucht die Länge nicht extra speichern 3.) meine Funktion ist universell einsetzbar. Man braucht keine globalen Variablen. 4.) falls die Datei 0 Bytes gross sein sollte, gibt es keinen Fehler (im Gegensatz zu LoadFromFileComplete) |
Re: Datei lesen auf "einmal"
@shmia:
Hatte früher auch oftmals einen String als Datenkontainer verwendet, vorallem wegen der einfacheren Handhabung, was das Freigeben/Kopieren/Übergeben der Daten anging, obwohl ich danach öfters auch mal ein Array of Byte dafür ranzog, welches die selben "Vorteile hat" ^^ Also gefiele mir das die Pascalversion von sniper_w wohl am Besten, vorallem da der auch noch ohne einen Stream auskommt ;) also z.B. so:
Delphi-Quellcode:
Aber wer hat hier bitte globale Variablen verwendet? :gruebel:
function S_pascal_ReadFileAsString(const FileName: string; var Data: String): Cardinal;
var FileHandle, BytesRead: Cardinal; begin FileHandle := CreateFile(PChar(FileName), GENERIC_READ, 0, nil, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0); if FileHandle = INVALID_HANDLE_VALUE then Error(0); // halt irgend ein Fehler, deer euch gefällt try Result := GetFileSize(FileHandle, nil); SetLength(Data, Result); ReadFile(FileHandle, Data^, Result, BytesRead, nil); if BytesRead <> Result then Error(0); // und nochma finally CloseHandle(FileHandle); end; end; Ach ja, jetzt setze ich für fowas eine eigene Struktur ein, wobi ich da aber auf die oben schon aufgeführten Vorteile verzichtet hab und jetzt nur noch die Daten, samt längenangabe zusammen hab ._. also für 32 Bit sähe es dann bei mir so aus (die Funktion gäbe TRUE zurück, wenn erfolgreich und in Data wären alle wichtigen Daten drin)
Delphi-Quellcode:
Type TDataG = packed Record
Len: LongInt; Data: Record End; End; PDataG = ^TDataG; Function ReadFile(Const FileName: AnsiString; Var Data: PDataG): Boolean; Und wenn einige jetzt noch bitte mit prüfen könnten, ob überhaupt genug Speicher vorhanden/reserviert wurde, dann wäre es auch nicht schlecht. |
Re: Datei lesen auf "einmal"
Zitat:
Bei GetMem würde ein Fehler auftreten, den man mit einem try...except...end;-Block abfangen könnte. Ich kann jetzt deinen letzten Post nicht ganz nachvollziehen, wie du das mit dem record machen möchtest, aber ich denke auch da würde ein Fehler auftreten sowas wie EOutOfMemory oder sowas (keine Ahnung jetzt ob das so heißt). |
Re: Datei lesen auf "einmal"
Ich weiß da ja, aber dieser Fehler bringt Nachteile ... (na ja, meinen eigenen MM kann ich auch so aufrufen, daß er erst garkeine Exception erzeugt :roll: )
Nimm mal z.B. mal sniper_w's ![]() Selbst wenn GetMem/SetLength keine exception erzeugt, dann würde immernoch in den nicht reservieren Speicher geschrieben. Und dann prüft och keiner, ob auch wirklich alles gelesen wurde .-. |
Re: Datei lesen auf "einmal"
Dafür sind ja die try-Blöcke:
Delphi-Quellcode:
So kann man auf sowas eingehen oder verstehe ich das Problem nicht?
try
//hier alles kritische ausführen, was evtl schiefgehen kann try //hier alles rein, von dem keine Exceptions angezeigt werden sollen except //der code wird nur ausgeführt wenn eine exception aufgetreten ist end; finally //hier alles rein, was UNBEDINGT ausgeführt werden muss, egal was zwischen try und finally passiert end; |
Re: Datei lesen auf "einmal"
Ich weiß das doch, nur machen das halt nicht alle Codes, die hier so rumliegen :zwinker:
|
Re: Datei lesen auf "einmal"
Dann müssen wir das eben nachholen. ;)
Welcher Code ist jetzt eigentlich der Aktuelle? Also welcher wird verwendet? |
Alle Zeitangaben in WEZ +1. Es ist jetzt 16:37 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