PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Delphi: Datei-Handling aus dem Hauptspeicher heraus?


aths
2008-11-22, 12:10:51
Soweit ich weiß unterstützt D, eine Datei in den Hauptspeicher zu legen und dort mit üblichen Dateioperationen zu hantieren. Nun programmiere ich leider nicht in D, sondern Delphi.

Ich lese eine mehrere MB große CSV-Datei Zeile für Zeile ein, was recht lange dauert. Wenn ich mit Blockread hantiere, kann ich die Datei im Bruchteil einer Sekunde einlesen, hab dann aber alles am Stück und nicht schön in Zeilen aufgeteilt. Bevor ich mich ransetze und den Riesenstring von Hand zerlege, meine Frage, ob man das eleganter lösen kann.

Meine alte Methode, mit memo1.readfromfile zu arbeiten und dann auf die einzelnen Zeilen zuzugreifen geht leider nicht, da die Zeilenlänge beim Memo begrenzt ist und die CSV-Datei einige Zeilen enthält, die länger sind.

Monger
2008-11-22, 12:23:39
Hab leider von Delphi auch keine Ahnung mehr, aber normalerweise gibt es für sowas die FileStreams.

Du öffnest also einen FileInput Stream, fragst üblicherweise in einer while Schleife nach ob denn der Stream schon zu Ende ist, holst dir vom Stream eine Zeile nach der anderen, und schließt den Stream danach wieder.

Nachteil bei sowas: da du hier Lesen und verarbeiten mischst, ist die Datei die ganze Zeit über gesperrt. Sollte z.B. ein anderer Prozess darauf Schreibrechte anfordern wollen (aus welchem Grunde auch immer), kann er das eine ganze Weile nicht.
Das zweite ist, dass man Streams auch sehr sorgsam wieder schließen muss, damit insbesondere im Fehlerfall die Datei wieder in einen robusten Zustand übergeht. Deshalb ist es für kleinere Daten meistens die bessere Idee, alles auf einen Rutsch einzulesen, den String auseinanderzufummeln (was im Idealfall auch nicht mehr als ein Einzeiler sein sollte), und auf einen Rutsch wieder zurückzuschreiben.

Berni
2008-11-22, 12:28:21
Bin jetzt kein Delphiprogrammierer aber was spricht denn gegen das Zerlegen des Strings? In C, Java und PHP ist das jedenfalls überhaupt kein Problem...

Gast
2008-11-22, 17:22:16
Die von Delphi (und anderen Hochsprachen) zur Verfügung gestellten Funktionen sind nicht mehr als Wrapper für die Funktionen des Win32-APIs, welche aber auch so nutzbar sind. Die Delphi-Pendants machen einem das Leben nur etwas einfacher - auf Kosten der Flexibilität und Kontrolle. Funktionen wie CreateFile() und ReadFile() arbeiten mit Handles, welche ggf. auch auf Objekte im Speicher "zeigen" können. Die win32.hlp - Abteilung "CreateFile" hilft da weiter ... nur eben hantiert man dann mit den Rohdaten. Memo.Lines nachzubilden würde zu einer Lösung führen die genauso langsam/schnell ist wie bei der Komponente selbst. Bequemlichkeit kostet eben :)

Was hier allerdings noch nicht erwähnt wurde ist die Möglichkeit der sogenannten "Memory Mapped Files" - vermutlich die Grundlage in "D". Dabei wird die Datei in den Speicher eingeblendet ohne das man diese auslesen muss. Man arbeitet also quasi "auf der Platte", was zB bei riesigen Bitmaps genutzt wird um diese anzuzeigen ohne Tonnen von Arbeitsspeicher zu benötigen. Der Ausgangspunkt dafür ist die API-Funktion "CreateFileMapping()" / "MapViewOfFile()". Die win32.hlp hilft hier weiter...

Nette Spielereien lassen sich damit auch machen: http://www.delphipraxis.net/topic48807_interprozesskommunikation+mitttels+memory+mapped+files.html

Was aber bleibt ist der Zugriff auf "lowlevel" - man bearbeitet die Datei wie sie gespeichert ist, muss also die einzelnen "Zeilen" selbst extrahieren und die Daten herauspflücken...

Und TStringList.LoadfromFile() hast Du auch schon durch? TStrings? Memo nutzt übrigens diese Komponenten um seine "Zeilen" zu speichern/laden und Längenbeschränkungen sind mir nicht bekannt - zumindest nach Delphi 2 nicht. Strings sind nämlich in Delphi nur durch den Speicher selbst begrenzt...bei der Ausgabe auf beschränktem Platz (wie bei Memo) werden diese natürlich umgebrochen etc.

aths
2008-11-22, 19:27:19
TStringList.LoadfromFile scheint genau das zu sein was ich brauchte. Danke!