¿Cuál es el mejor método para leer un doble de un archivo binario creado en C?

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

  •  08-07-2019
  •  | 
  •  

Pregunta

Un programa C escupe dobles consecutivos en un archivo binario. Deseo leerlos en Python. Intenté usar struct.unpack('d',f.read(8))

EDITAR: Usé lo siguiente en C para escribir un número doble al azar

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

Los errores ahora están corregidos pero no puedo leer el primer valor. para un número total de 0.000 .. lo lee como 3.90798504668055 pero el resto está bien.

¿Fue útil?

Solución

Creo que en realidad estás leyendo el número correctamente, pero la pantalla te confunde. Cuando leo el número de su archivo proporcionado, obtengo " 3.907985046680551e-14 " - esto es casi, pero no del todo cero (0.000000000000039 en forma expandida). Sospecho que su código C solo lo imprime con menos precisión que Python.

[Editar] Acabo de intentar leer el archivo en C, y obtengo el mismo resultado (aunque un poco menos de precisión: 3.90799e-14) (usando printf ("% g " ;, val)), así que piense que si este valor es incorrecto, sucede en el lado de la escritura, en lugar de la lectura.

Otros consejos

¿Podría por favor elaborar sobre "no funcionó"? ¿Se bloqueó el comando? ¿Los datos salieron mal? ¿Qué pasó realmente?

Si el comando falla:

  • Por favor, comparta la salida de error del comando

Si los datos simplemente salieron mal:

  • ¿Los sistemas que crean y leen los datos tienen la misma resistencia? Si uno es big-endian y el otro es little-endian, entonces debe especificar una conversión de endianness en su cadena de formato.

  • Si la resistencia de las dos computadoras es la misma, ¿cómo se escribieron los datos en el archivo, exactamente ? ¿Tú sabes? Si lo hace, ¿cuál fue el valor escrito en el archivo y cuál fue el valor incorrecto que obtuvo?

Primero, ¿ha probado pickle ? Nadie ha mostrado ningún código de Python todavía ... Aquí hay un código para leer en binario en 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()

Donde la f aquí especifica números de precisión simple, flotantes de 4 bytes. Encuentre el tamaño de sus datos por entrada y úselo.

Para datos no binarios, puede hacer algo simple como esto:

   tmp=[]
   for line in open("data.dat"):
                tmp.append(float(line))
  • f.read (8) podría devolver menos de 8 bytes
  • Los datos pueden tener diferente alineación y / o resistencia:

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

El método mejor sería utilizar un archivo de texto ASCII:

  

0.0
  3.1416
  3.90798504668055

en que sería portátil y funcionaría con cualquier tipo de implementación de punto flotante hasta cierto punto.

La lectura de datos binarios sin procesar de una dirección de memoria de double no es portátil en absoluto, y está destinada a fallar en alguna implementación diferente.

Por supuesto, puede usar un formato binario para la compacidad, pero una función de escritura C portátil que se escriba en ese formato no se parecería en absoluto a su fragmento.

Como mínimo, el código debe estar rodeado por una serie de ifs / ifdefs que comprueban que la representación de memoria de double s utilizada por la máquina actual coincide exactamente con la esperada por el intérprete de Python.

Escribir dicho código sería difícil, por eso sugiero la solución fácil, limpia, portátil y legible para humanos del texto ASCII.

Esta sería mi definición de "mejor".

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top