PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : C Dateizugriff


rotalever
2007-05-18, 18:44:03
Hallo,
ich habe eine große Datei mit Daten, z.B. 8GB groß. Auf diese möchte mit einem Programm, programmiert in C, an beliebige Stellen zugreifen. Gibt es irgendeine besonders praktische (und schnelle?) Methode an eine beliebige Position einer Datei zuzugreifen? Oder muss man die Datei erst komplett bis zu der gewünschten Position auslesen um dann die gewünschten Daten zu bekommen?

Besserwissend
2007-05-18, 19:15:53
Mir fällt da auf Anhieb "fseek" ein. Eventuell gibt es da noch Dateisystemabhängige/betriebssystemabhängige Bibliotheken die schneller sind.
Je nach Zugriffshäufigkeit kann es von Vorteil sein, die Datei zu indizieren.
Wenn Du öfter auf große Datenmengen beliebig zugreifen mußt, empfiehlt es sich die Daten in eine Datenbank zu laden.

rotalever
2007-05-18, 20:25:21
Also es muss schonmal auf jedenfall Systemübergreifend funktionieren (Win, Linux).

Was bringt mir das indizieren? Ist das sinnvoll wenn ich exakt weiß, auf welches byte, bzw. byte-Folge ich zugreifen will? Vll. verstehe ich den Begriff Indizieren auch einfach nur falsch...

Zu Datenbanken: Die Datenbank muss dann ja auch wieder im Speicher liegen oder nicht? Und das geht ja nicht aufgrund der Größe.

Im Endeffekt geht es darum ein Bild aus 16bit oder 32bit Graustufen RAW-Daten in ein spezielles Format umzuwandeln, für das ich eben einen Konvertierer schreibe. Wenn dass mit dem random access in Dateien nicht gut geht muss ich mir wohl leider was anderes überlegen. Wenn ich von random access spreche meine ich natürlich nicht, dass ich ständig hier ein byte und dort ein byte lese, sondern immer einigermaßen große Blöcke aber eben von verschiedenen Stellen.

Es soll darauf hinauslaufen, dass vll. Insgesamt 768MB Hauptspeicher während der Laufzeit des Konvertierers verbraucht werden dürfen, bei einer zu bearbeitenden Datei von den angesprochenden rund 8GB. Das komprimierte Endergebnis werden dann hoffentlich unter 100MB, aber das interessiert hier ja erst einmal nicht.



edit:
Hab mir mal fseek angeschaut, scheint wohl wirklich das zu sein, wonach ich suche!

rotalever
2007-05-18, 21:05:20
Wenn ich fsetpos in zusammenhang mit fgetpos benutze würde es doch vll. etwas schneller gehen, da durch das fgetpos möglicherweise schon vorher Positionierungsinformationen gesammelt werden?
Natürlich müsste man dann die Datei vorher einmal komplett scannen.

"Note: fgetpos is implemented here as a macro which calls fseek." von http://tigcc.ticalc.org/doc/stdio.html#fsetpos
bedeutet dann ja wohl, dass es doch nichts bringt^^

Besserwissend
2007-05-18, 22:27:18
Zu Datenbanken: Die Datenbank muss dann ja auch wieder im Speicher liegen oder nicht? Und das geht ja nicht aufgrund der Größe.

Datenbanken halten nicht immer alle Daten im Speicher. Das können ja unter Umständen auch einige Petabyte sein. Z.B. befindet sich ein (oft Baumartig aufgebauter) Index, der auf die auf dem Permanentspeicher (Festplatte) abgelegten Daten verweist und häufig benötigte Daten (Cache) im Speicher.
Für den Anwendungszweck "RAW Daten", also Pixel (x,y) + Meßwerte (Farbkanäle etc.) lohnt sich eine Standard-DB nicht.
Vielleicht gibt es ja "Pixel Datenbanken" oder sowas ähnliches.

In der Regel sollte ein vernünftiges RAW-Format doch immer (verlustfrei) komprimiert worden sein ?
Falls nicht, müßten die Daten doch als "sortierter Strom" vorliegen.
Meiner Meinung nach bieten sich mehrere Ansätze:

A.
0. Falls nötig, RAW-Format dekomprimieren.
1. Die Daten, in der Reihenfolge, wie sie Dein Algorithmus benötigt sortieren (-> mit MergeSort und Derivaten geht das sequentiell). Das kostet höchstens Plattenplatz und der ist "gratis"
2. konvertieren mit Deinem Algorithmus aber dann mit sequentiellem Lesen auf der "sortierten Datei".

B.
Wie Du schon angedeutet hast: die Datei in größeren Blöcken einlesen und auf den Blöcken arbeiten

C.
Mit fseek hin und herspringen :P

D.
Den Algorithmus ändern :)

rotalever
2007-05-19, 10:26:56
In der Regel sollte ein vernünftiges RAW-Format doch immer (verlustfrei) komprimiert worden sein ?

Ist es aber nicht, sind einfach 16bit Integerwerte aneinandergereit ;) und davon halt ne Menge. Es ist halt mein "eigenes" RAW-Format
Das RAW-Format ist ja auch nur ein Übergangsformat, dass im Endeffekt nur einmal verwendet werden soll und später eben durch das entsprechende komprimierte Format ersetzt werden soll, dessen Erstellung aber die genannten Probleme aufweist.

Vll. ist es wirklich eine gute Idee, die Daten vorher schon einmal etwas auf mehrere Dateien aufzuteilen. Vll. vereinfacht das sogar die Programmierarbeit ;)

muhkuh_rs
2007-05-21, 19:38:41
fseek wird dir bei 8 GB großen Dateien nicht helfen, da es auf 2GB limitiert ist. Es gibt nicht portable Funktionen, die mit 64 bit großen Adressen arbeiten. Entweder du führst selbst irgendeine Art von Kompatibilitätslayer ein oder Du nimmst eine fertige Library wie boost::filesystem.

rotalever
2007-05-21, 20:03:03
Wieso ist es limitiert, ich dachte es hätte ein long int (64 bit int) als Positionsangabe??

muhkuh_rs
2007-05-22, 15:16:12
Ja, es ist ein long int. Welche Genauigkeit long int hat, hängt aber vom Compiler ab. Unter 32 bit Systemen ist ein long int z.B. üblicherweise 32bit groß und geht von –2147483648 bis 2147483647. Das reicht bis 2GB.

Es nützt auch nichts, das fseek in mehreren Schritten aufzurufen, mit SEEK_CUR als Ausgangspunkt, da es nicht erlaubt ist, die Position so zu versetzen, dass sie nicht mehr mit ftell auslesbar ist (Rückgabewert long).

rotalever
2007-05-22, 15:30:25
Dann muss ich wohl das Pendant von Boost nehmen, wäre halt schön gewesen, da weniger Abhängigkeiten aber was solls.

ScottManDeath
2007-05-22, 17:32:48
Oder die Datei per OS Funktion in den Speicher mappen und das OS dann das Paging erledigen lassen.

HellHorse
2007-05-22, 20:23:47
Oder die Datei per OS Funktion in den Speicher mappen und das OS dann das Paging erledigen lassen.
Was aber bei 8GB wohl ein 64bit OS brauchen würde, oder?

del_4901
2007-05-22, 20:30:44
Was aber bei 8GB wohl ein 64bit OS brauchen würde, oder?
das könnte auch noch mit PAE klappen.

ScottManDeath
2007-05-22, 23:34:26
Man könnte Teile der Datei, die man benötigt mappen, und sich so nur das was man gerade braucht in den virtuellen Speicher holen.

Besserwissend
2007-05-23, 00:49:29
Wenn ich fsetpos in zusammenhang mit fgetpos benutze würde es doch vll. etwas schneller gehen, da durch das fgetpos möglicherweise schon vorher Positionierungsinformationen gesammelt werden?
Natürlich müsste man dann die Datei vorher einmal komplett scannen.

"Note: fgetpos is implemented here as a macro which calls fseek." von http://tigcc.ticalc.org/doc/stdio.html#fsetpos
bedeutet dann ja wohl, dass es doch nichts bringt^^

Das fgetpos ein Makro für fseek ist, ist nicht immer der Fall. Das hängt von der Implementierung des ANSI-Standards ab.
Für int fsetpos (FILE *fp, const fpos_t *pos) ist fpos_t ein primitiver Datentyp.
Schau mal in die stdio.h des Compilerherstellers/Betriebssystems Deines Vertrauens.
Bei mir ist fpos_t mittels typedef festgelegt; allerdings long :-), kann bei Dir vielleicht anders sein (unsigned long long int :-))?
Eventuell kannst Du fsetpos, fgetpos doch benutzen.

del_4901
2007-05-23, 01:35:56
Ich würde, wie ScottMan schon vorschlug, mir den Teil den ich grad brauche in den virtuellen Speicher mappen, oder ein 64bit OS nehmen und mir alles in den virtuellen Speicher mappen. PAE würde zwar auch gehn, aber PAE ist nicht wirklich zuverlässig.

rotalever
2007-05-23, 14:43:52
Was aber, wenn der Virtuelle Speicher des Systems zu klein ist? Es liegt zudem nicht immer ein 64bit System vor! Geschweige denn habe ich einen 64bit Prozessor zum testen und die Unterstützung von PAE unter windows lässt auch zu wünschen übrig.
Ergo muss ich es anders machen, auch wenn es vermutlich unter meiner Entwicklungsumgebung (Linux) mit PAE funktionieren würde.

Desweiteren ist es auch nicht unbedingt sinnvoll erst einmal alle Daten in den virtuellen Arbeitspeicher zu laden, da diese dann im schlechtesten Falle innerhalb einer Festplatte kopiert werden -> Bremse beim Startvorgang. Das wäre natürlich nicht katastrophal aber es ist ja auch nicht unbedingt nötig.

del_4901
2007-05-23, 15:04:23
Was aber, wenn der Virtuelle Speicher des Systems zu klein ist? Es liegt zudem nicht immer ein 64bit System vor! Geschweige denn habe ich einen 64bit Prozessor zum testen und die Unterstützung von PAE unter windows lässt auch zu wünschen übrig.
Ergo muss ich es anders machen, auch wenn es vermutlich unter meiner Entwicklungsumgebung (Linux) mit PAE funktionieren würde.

Desweiteren ist es auch nicht unbedingt sinnvoll erst einmal alle Daten in den virtuellen Arbeitspeicher zu laden, da diese dann im schlechtesten Falle innerhalb einer Festplatte kopiert werden -> Bremse beim Startvorgang. Das wäre natürlich nicht katastrophal aber es ist ja auch nicht unbedingt nötig.

Der virtuelle Speicher in einem 64bit System ist garantiert nicht zu klein!
Bei nem 32biter musst du halt mit deinen 4Gb haushalten.

BTW: Da wird gar niks kopiert ... der mappt dir einfach die Datei in deinen Adressraum.
http://en.wikipedia.org/wiki/Memory-mapped_file

rotalever
2007-05-23, 15:23:28
Der virtuelle Speicher in einem 64bit System ist garantiert nicht zu klein!
Bei nem 32biter musst du halt mit deinen 4Gb haushalten.

Wenn ich sowieso haushalten muss, kann ich es auch direkt selbst machen...;)


BTW: Da wird gar niks kopiert ... der mappt dir einfach die Datei in deinen Adressraum.
http://en.wikipedia.org/wiki/Memory-mapped_file
Ok, dann hatte ich das falsch verstanden:redface: