2009-03-10 7 views
5

Ein C-Programm spuckt aufeinanderfolgende Doppeleingaben in eine Binärdatei aus. Ich möchte sie in Python lesen. Ich habe versucht, struct.unpack('d',f.read(8))Was ist die beste Methode, um ein Double aus einer in C erstellten Binärdatei zu lesen?

EDIT: habe ich die folgenden in C eine Zufallszahl Doppel

r = drand48(); 
fwrite((void*)&r, sizeof(double), 1, data); 

die Fehler behoben werden jetzt zu schreiben, aber ich kann nicht den ersten Wert lesen. für eine alle 0.000 .. Nummer liest es als 3.90798504668055, aber der Rest ist in Ordnung.

+0

Es könnte mit falscher Endlichkeit verbunden sein (was zuerst das niedrigstwertige Byte kommt oder nicht). Zeigen Sie, welche Bytes Sie lesen möchten. – jfs

+0

Es tut mir leid. Ich habe das Problem fast behoben, also habe ich es als beantwortet markiert. Ich würde gerne sehen, dass die erste Nummer richtig gelesen wird. – gnosio

+0

Können Sie einen Dump der ersten 40 Bytes der Datei zusammen mit dem Code, den Sie gerade lesen, bereitstellen? –

Antwort

3

Ich glaube, Sie sind die Nummer richtig tatsächlich zu lesen, aber sind immer durch die Anzeige verwirrt. Wenn ich die Nummer aus Ihrer Datei lese, bekomme ich "3.907985046680551e-14" - das ist fast, aber nicht ganz Null (0.000000000000039 in erweiterter Form). Ich vermute, dass Ihr C-Code es nur mit weniger Genauigkeit als Python drucken wird.

[Bearbeiten] Ich habe gerade versucht, die Datei in C zu lesen, und ich bekomme das gleiche Ergebnis (obwohl etwas weniger Präzision: 3.90799e-14) (mit printf ("% g", val)), also ich denke, wenn dieser Wert falsch ist, ist es auf der Schreibseite passiert, anstatt das Lesen.

+0

Hey Brian, du hast es genagelt. Ich war faul, es zu erweitern :(. Die Genauigkeit ist der Grund für 2 verschiedene Werte. Danke für die Hilfe. – gnosio

1

Könnten Sie bitte näher auf "hat nicht funktioniert"? Ist der Befehl abgestürzt? Sind die Daten falsch? Was wirklich passierte?

Wenn der Befehl abgestürzt:

  • Bitte teilen Sie den Fehler Ausgabe des Befehls

Wenn die Daten einfach falsch herauskam:

  • die Systeme tun, die Erstellung und Lesen Sie die Daten haben die gleiche Endianz? Wenn der eine Big-Endian ist und der andere ein Little-Endian, dann müssen Sie in Ihrer Formatzeichenfolge eine Endianness-Konvertierung angeben.

  • Wenn die Endianität der beiden Computer gleich ist, wie wurden die Daten in die Datei geschrieben, genau? Wissen Sie? Wenn ja, was war der Wert, der in die Datei geschrieben wurde und was war der falsche Wert, den du bekommen hast?

0
  • f.read(8) könnte zurückkehren weniger als 8 Bytes
  • Daten haben könnten unterschiedliche Ausrichtung und/oder Endian:

    >>> for c in '@=<>': 
    ...  print repr(struct.pack(c+'d', -1.05)) 
    ... 
    '\xcd\xcc\xcc\xcc\xcc\xcc\xf0\xbf' 
    '\xcd\xcc\xcc\xcc\xcc\xcc\xf0\xbf' 
    '\xcd\xcc\xcc\xcc\xcc\xcc\xf0\xbf' 
    '\xbf\xf0\xcc\xcc\xcc\xcc\xcc\xcd' 
    >>> struct.unpack('<d', '\xbf\xf0\xcc\xcc\xcc\xcc\xcc\xcd') 
    (-6.0659880001157799e+066,) 
    >>> struct.unpack('>d', '\xbf\xf0\xcc\xcc\xcc\xcc\xcc\xcd') 
    (-1.05,) 
    
0

Die besten Verfahren ein verwenden wäre ASCII-Textdatei:

0,0
3,1416
3,90798504668055

, dass sie mit jeder Art von Gleitkomma-Umsetzung zu einem gewissen Grad beweglich und arbeiten würden.

Das Lesen roher Binärdaten von einer double 's Speicheradresse ist überhaupt nicht portierbar und muss in einigen anderen Implementierungen fehlschlagen.

Sie können natürlich ein Binärformat für die Kompaktheit verwenden, aber eine portable C-Funktion, die in diesem Format schreibt, würde Ihrem Snippet überhaupt nicht ähneln.

Zumindest sollte der Code von einer Reihe von ifs/ifdefs umgeben sein, die überprüfen, dass die von der aktuellen Maschine verwendete Speicherrepräsentation von double genau mit der vom Python-Interpreter erwarteten übereinstimmt.

Schreiben solchen Codes wäre schwierig, weshalb ich die einfache, saubere, tragbare und menschenlesbare Lösung von ASCII-Text vorschlagen.

Dies wäre meine Definition von "best".

+0

Hallo Aib, ich wünschte, ich könnte das tun, aber es ist ein Speicherauszug und ich habe nicht Kontrolle darüber, wie es exportiert wird. Ich habe guten Erfolg beim Auspacken aber aus irgendeinem Grund liest das erste Double nicht richtig. – gnosio

+0

Ich hatte das vermutet, wollte aber trotzdem meinen zukünftigen Lesern zeigen. Ich bin froh, dass du dein Problem gelöst hast. – aib

1

Zuerst haben Sie versucht pickle? Niemand hat bisher noch keine Python-Code gezeigt ... Hier einige Code ist binär in Python zum Lesen:

import Numeric as N 
import array 
filename = "tmp.bin" 
file = open(filename, mode='rb') 
binvalues = array.array('f') 
binvalues.read(file, num_lon * num_lat) 
data = N.array(binvalues, typecode=N.Float) 

file.close() 

Wo die f hier mit einfacher Genauigkeit angegeben, 4-Byte-Fließ, Zahlen. Finden Sie die Größe Ihrer Daten pro Eintrag und verwenden Sie diese.

Für nicht binäre Daten könnten Sie etwas Einfaches wie dies tun:

tmp=[] 
    for line in open("data.dat"): 
       tmp.append(float(line)) 
+0

Hey Alex, ich habe Pickle versucht, aber für mein Problem bin ich nicht garantiert, dass alle Werte Double sind. Sie könnten Ints, Floats oder Doubles sein. Alles, was ich weiß, ist der Ort und die Art des zu lesenden Wertes. Danke für die Hilfe aber :) – gnosio

Verwandte Themen