Qual è il metodo migliore per leggere un doppio da un file binario creato in C?

StackOverflow https://stackoverflow.com/questions/631607

  •  08-07-2019
  •  | 
  •  

Domanda

Un programma C suddivide i doppi consecutivi in ??un file binario. Vorrei leggerli in Python. Ho provato a usare struct.unpack('d',f.read(8))

EDIT: Ho usato quanto segue in C per scrivere un doppio numero casuale

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

Gli errori sono ora corretti ma non riesco a leggere il primo valore. per un numero di tutti 0.000 .. lo legge come 3.90798504668055 ma il resto va bene.

È stato utile?

Soluzione

Penso che tu stia leggendo il numero correttamente, ma ti confondi sul display. Quando leggo il numero dal tuo file fornito, ottengo " 3.907985046680551e-14 " - questo è quasi ma non del tutto zero (0,000000000000039 in forma espansa). Sospetto che il tuo codice C lo stia semplicemente stampando con meno precisione di quanto lo sia Python.

[Modifica] Ho appena provato a leggere il file in C e ottengo lo stesso risultato (anche se con una precisione leggermente inferiore: 3.90799e-14) (usando printf ("% g " ;, val)), quindi I pensa che se questo valore non è corretto, è successo sul lato della scrittura, piuttosto che sulla lettura.

Altri suggerimenti

Potresti per favore approfondire " non ha funzionato " ;? Il comando si è bloccato? I dati sono risultati errati? Che cosa è effettivamente successo?

Se il comando si è bloccato:

  • Si prega di condividere l'output dell'errore del comando

Se i dati sono semplicemente risultati errati:

  • I sistemi che creano e leggono i dati hanno lo stesso endianness? Se uno è big-endian e l'altro è little-endian, devi specificare una conversione di endianness nella tua stringa di formato.

  • Se l'endianness dei due computer è la stessa, come sono stati scritti i dati nel file, esattamente ? Lo sai? Se lo fai, qual è stato il valore scritto nel file e qual è stato il valore errato che hai ottenuto?

In primo luogo, hai provato pickle ? Nessuno ha ancora mostrato alcun codice Python ... Ecco un po 'di codice per leggere in binario in Python:

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()

Dove la f qui specificava numeri a precisione singola, flottanti a 4 byte. Trova le dimensioni dei tuoi dati per voce e utilizzale.

Per i dati non binari potresti fare qualcosa di semplice come questo:

   tmp=[]
   for line in open("data.dat"):
                tmp.append(float(line))
  • f.read (8) potrebbe restituire meno di 8 byte
  • I dati potrebbero avere allineamento e / o endianness diversi:

    >>> 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,)
    

Il miglior metodo sarebbe usare un file di testo ASCII:

  

0.0
  3.1416
  3.90798504668055

in quanto sarebbe portatile e funzionerebbe con qualsiasi tipo di implementazione in virgola mobile fino a un certo punto.

La lettura di dati binari non elaborati da un indirizzo di memoria di double non è affatto portatile ed è destinata a fallire in un'implementazione diversa.

Puoi ovviamente usare un formato binario per compattezza, ma una funzione C portatile che scrive in quel formato non assomiglierebbe affatto al tuo frammento.

Per lo meno, il codice dovrebbe essere circondato da una serie di ifs / ifdefs che verificano che la rappresentazione in memoria di double utilizzata dalla macchina corrente corrisponda esattamente a quella prevista dall'interprete Python.

Scrivere questo codice sarebbe difficile, motivo per cui sto suggerendo la soluzione semplice, pulita, portatile e leggibile dall'uomo del testo ASCII.

Questa sarebbe la mia definizione di " best " ;.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top