Frage von offeltoffel, 66

Wie kann ich Integer-Datenreihen so abspeichern, dass sie weniger Speicherplatz brauchen als eine ASCII-Textdatei?

Hallo zusammen,

ich habe zwei Datenreihen der Länge 2150, welche im Format Integer (8bit) vorliegt. Die nächstkleinere Stufe reicht leider nicht aus, um alle Daten abzubilden.

Diese Datenreihen werden am Ende jedes Simulations-Zyklus als ASCII-Text abgespeichert. Als Trennzeichen dient das Leerzeichen. Derzeit haben die Dateien eine Größe von 27KB. Habt ihr eine Idee, wie ich sie noch kleiner bekomme? Jedes Byte zählt. CSV? Binär?

Hilfreichste Antwort - ausgezeichnet vom Fragesteller
von AnReRa, 44

Ähm, ich verstehe die Frage nicht ganz.
Zwei mal 2150 8-Bit Werte sind genau  4300 Byte Speicher.
Warum um Himmelswillen speicherst Du die nicht einfach wie sie sind als Binärdatei ?




Kommentar von offeltoffel ,

Das Modell ist in Fortran geschrieben. Es gibt, wie gesagt, zwei Datenreihen mit Integerwerten von 0 bis 1000. Wenn ich sie als Datenmatrix mit dem Standardbefehl WRITE(unit,*) X abspeichere, legt er eine ASCII-Datei an.

Hätte eine Binärdatei wirklich nur 4,3KB? Ich weiß ja nicht, was noch alles dafür gespeichert wird, dass die Binärdatei auch lesbar ist. Sie wird ja auch einen Header haben, oder Trennbefehle oder so. Sie muss halt so abgespeichert werden, dass ich sie mit Python wieder einlesen kann.

Kommentar von AnReRa ,

Also bei Fortran muss ich im Detail passen.
Aber die Idee ist folgende:

Die Zahl "254" binär "11111110" belegt im Hauptspeicher 1 Byte.
Wenn Du Die mit WRITE schreibst, dann landet die Zeichenfolge "254" sprich 3 Zeichen in der Datei und belegen damit 3x 8Bit also 24 Bit.

Was verstehst Du unter "lesbar" ?
Eine Datei die Du direkt lesen kannst wird immer ASCII sein - inklusive Leerzeichen und sonstiger Formatierung. Eine reine Binärdatei kannst Du nur mit einem entsprechende Editor (oder eben selbst geschriebenen Programm) ansehen. Aber für die reine Weiterverarbeitung braucht der Rechner diese Formatierungsinformationen nicht !
Aber ob FORTRAN nun binär schreiben kann weiss ich nicht.
WRITE ist dafür offenbar nicht geeignet.

Sie muss halt so abgespeichert werden, dass ich sie mit Python wieder einlesen kann

Also auf der einen Seite soll die Datei kleiner werden, auf der anderen Seite muss sie aber genau so formatiert bleiben wie sie ist ????
Was denn nun ?

Kommentar von AnReRa ,

Hier steht was dazu:

http://www.exp.univie.ac.at/sc/proglang-8.pdf

Jetzt mußt Du nur in Python schauen, wie Du Binärdateien wieder einlesen kannst.

Kommentar von offeltoffel ,

es hat geklappt, er hat sie mal als Binär abgespeichert (hab die Endung .dat verwendet). Jetzt kommt der Knaller, die Dateien haben jetzt 42KB statt vorher 27KB.

Ne Idee, woran das liegen könnte? Es sind genau 2151 * 2 * 16bit, die ich nacheinander (sequential) abspeichere.

Kommentar von AnReRa ,

42 KB oder 4.2KB ? Zähl nochmal die Stellen ...

Ansonsten schau mal mit einem HEx-Editor / Viewer in die Datei rein.
Du weißt ja was in SCII stehen sollte ...

Kommentar von offeltoffel ,

Tatsächlich 42KB, wirklich komisch. Fortran speichert die Einträge separat als "Records". Womöglich muss er vor und nach jedem Record zusätzliche Zeichen reservieren ...

Mit einem HEx-Editor kann man Binärdateien anschauen? Das klingt praktisch, werde ich morgen ausprobieren, wenn ich wieder im Büro bin!

Kommentar von AnReRa ,

Vermutlich muss man Fortran 'sagen', dass der Record jeweils nur 1 Byte groß ist.

Kommentar von AnReRa ,

Ich sehe dann zwei Möglichkeiten:

Du verwendest nicht mehr den 'int' zum speichern sondern arbeitest auf einem Record. Spicht Du definierst einen Record mit 2151 'int8' werten und speicherst diesen record mit einem einzelne WRITE Befehl.

Andersherum definierst Du einen Record, der  genau 1 'int8' Wert enthält und arbeitest mit diesem im Programm.

Aber sinnvoll ist nur die erste Variante, weil das Programm einfach viel schneller arbeitet.

Aber frag mich nicht wie der 'Record' in Fortran zu definieren/deklarieren ist. Da musst Du wohl das Handbuch konsultieren ...

Kommentar von offeltoffel ,

Durch deine/eure Hilfe bin ich inzwischen soweit, dass ich ein konkretes Ziel habe und die Basis des Problems beschreiben kann. Damit kann ich jetzt in stackoverflow.com aufwarten. Vielen Dank bis dahin!

Kommentar von AnReRa ,
Kommentar von offeltoffel ,

Danke, ich habe das Problem inzwischen gefunden! Dank des Tipps mit dem Hex-Editor habe ich herausgefunden, dass er am Anfang und Ende jedes Records angibt, wie viele Elemente er enthält (und das nicht in 16bit sondern in 32bit). Das hilft anscheinend vielen Programmen, schneller auszulesen. Übersetzt in Integer sahen meine Zeilen also immer so aus:

2 WertA1 2

2 WertA2 2

2 WertA3 2

...

2 WertA2101 2

2 WertB1 2

2 WertB2 2

...

2 WertB2101 2


Anstatt also 2101 Zeilen * 2 Spalten * 16bit(=2 byte) = 8,4KB erhielt ich 4202 Zeilen * 1 Spalten * 2byte + 4202 Zeilen * 2 Spalten * 4byte  = 42,02KB.

Ich habe im Leben nie etwas mit Binär oder Hex gemacht, darum ist das alles höchst verwirrend für mich, aber am Ende auch alles logisch, nachvollziehbar und eine spannende neue Herausforderung.

Der gesuchte Zusatz in Fortran im OPEN-Statement lautet übrigens "access='stream'"

OPEN (unit=11, file = 'D:\binary2.dat', form='unformatted', access='stream')

E voilà: meine Dateien sind jetzt 8,2KB groß :)

Kommentar von offeltoffel ,

Also auf der einen Seite soll die Datei kleiner werden, auf der anderen
Seite muss sie aber genau so formatiert bleiben wie sie ist ????
Was denn nun ?

Nicht direkt. Sie muss nciht genau so formatiert bleiben, wie sie ist. Sie muss nur von einem anderen Programm wieder eingelesen werden können.

Solange ich weiß, wie die Binär-Datei aufgebaut wird, kann ich sie in Python ja wieder entschlüsseln. Wenn ich aber keine Ahnung habe, wie Fortran die Binärdatei mit Daten füllt, kann ich auch kein Python-Script schreiben, das sie wieder auseinanderpflückt.

Ich muss nur eben über 80 Millionen Modellläufe parat halten. Stell dir das vor wie eine Datenbank. Auf Wunsch muss ein bestimmter Lauf gesucht werden, in ASCII zurückgewandelt und dann z.B. visualisiert werden. Damit ich aber eben überhaupt so viele Läufe auf meiner Platte speichern kann, suche ich nach schlankeren Lagerungssystemen.

Antwort
von Omnivore13, 31

äääää binär abspeichern? Verbraucht EXAKT nur 8 Bit je Zahl.

Aber seit wann ist ein Integer 8 Bit?

Kommentar von offeltoffel ,

In Fortran gibt man bei der Deklaration an, welche Bit-Tiefe für die Variable gewünscht ist, weil dann ein entsprechender Teil im Speicher reserviert wird. Ich meinte auch eigentlich 16bits (unsigned 0 bis 65535) -> in Fortran Integer*2.

Hätte eine Binärdatei wirklich nur 2 bytes * 2 * 2150 = 8,6Kb? Ich weiß ja nicht, was noch alles dafür gespeichert wird, dass die Binärdatei auch lesbar ist. Sie wird ja auch einen Header haben, oder Trennbefehle oder so. Sie muss halt so abgespeichert werden, dass ich sie mit Python wieder einlesen kann.

Kommentar von Omnivore13 ,

Sie wird ja auch einen Header haben, oder Trennbefehle oder so.

Das kommt darauf an wie man es organisiert. Wenn DU die Werte binär einfach hintereinander abspeicherst, kannst du sie später mit dem selben Prinzip doch auch wieder einlesen. Da bedarf es kein Header oder sonst was!

Ein Header gibt es zum Beispiel bei BMPs. das sind auch Binärdateien, welche pro Zeile 3 Abschlussbytes haben und ein Header von 80 Byte. Alles andere ist normal binäre Nutzdaten.

Und so kannst du es doch auch machen: Speicher deine Nutzdaten binär ab und lese sie in der gleichen Reihenfolge wieder ein.

Kommentar von offeltoffel ,

Klingt einleuchtend! Jetzt muss ich nur noch googlen und verstehen, wie man in Fortran Binär-Dateien abspeichert. Und am besten eine Routine schreiben, die mir die Binäre-Dateien auf Wunsch in ASCII umwandelt, wenn ich z.B. Inhalte überprüfen muss.

Du hast nicht zufällig einen Befehl dafür parat?

Kommentar von Omnivore13 ,

Tut mir leid....hab zwar Informatik studiert und bin nicht nur 2 sprachig unterwegs ^^ Aber Fortran habe ich noch nie in meinem Leben genutzt. Tut mir leid..

Kommentar von offeltoffel ,

kein Ding, hab schon eine Anleitung gefunden. Dafür beherrscht du ein paar Sprachen vermutlich fließend, um mal die Metaphorik zu nutzen. Ich bin kein Informatiker, sondern brauche das Programmieren nur als Werkzeug für meine Arbeitsaufgaben.

Kommentar von Omnivore13 ,

hehe jo....du wirst das schon packen. Und falls Kodespeicher mehr sein darf, als dein Datenspeicher, dann schau dir mal den Huffmann-Kode an. Falls deine Daten nämlich nicht Gleichverteilt sind kannst du da was Speicher drücken.

Keine passende Antwort gefunden?

Fragen Sie die Community