Qual é o melhor método para ler uma dupla de um arquivo binário criado em C?

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

  •  08-07-2019
  •  | 
  •  

Pergunta

Um programa C cospe duplos consecutivos em um arquivo binário. Eu gostaria de lê-los em Python. Eu tentei usar struct.unpack('d',f.read(8))

EDIT: Eu usei o seguinte em C para escrever um número double aleatória

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

Os erros são fixos, mas eu não consigo ler o primeiro valor. para um todo 0.000 .. Número lê-lo como 3,90798504668055 mas o resto está bem.

Foi útil?

Solução

Eu acho que você está realmente lendo o número corretamente, mas estão a ficar confuso com a exibição. Quando leio o número do seu arquivo fornecido, eu recebo "3.907985046680551e-14" - isso é quase, mas não completamente zero (,000000000000039 em forma expandida). Eu suspeito que o seu código C é apenas imprimi-lo com menos precisão do que python é.

[Edit] Eu apenas tentei ler o arquivo em C, e eu obter o mesmo resultado (embora um pouco menos de precisão: 3.90799e-14) (usando printf ( "% g", val)), então eu acho Se esse valor estiver incorreto, isso aconteceu no lado da escrita, ao invés da leitura.

Outras dicas

Você poderia por favor elaborar sobre "não funcionou"? Será que o acidente de comando? Será que os dados saem errado? O que realmente aconteceu?

Se o comando caiu:

  • Por favor, compartilhe a saída de erro do comando

Se os dados simplesmente saiu errado:

  • Será que os sistemas que criar e ler os dados têm a mesma ordenação? Se um é big-endian, eo outro é little-endian, então você precisa especificar uma conversão endianness em sua cadeia de formato.

  • Se a ordenação dos dois computadores são os mesmos, como foi os dados gravados no arquivo, exatamente ? Você sabe? Se o fizer, então o que era o valor escrito para o arquivo e qual foi o valor incorreto você saiu?

Em primeiro lugar, você já tentou picles ? Ninguém mostrou qualquer código Python ainda ... Aqui está um código para a leitura em binário em 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()

Quando o f aqui especificado de precisão simples, de 4 bytes flutuante, números. Encontrar o tamanho de seus dados é por entrada e uso isso.

Para dados não binários que você poderia fazer algo simples como isto:

   tmp=[]
   for line in open("data.dat"):
                tmp.append(float(line))
  • f.read(8) pode retornar menos de 8 bytes
  • Os dados podem ter diferentes alinhamento e / ou endianness:

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

O melhor método seria a utilização de um arquivo de texto ASCII:

0.0
3,1416
3,90798504668055

em que seria portátil e trabalhar com qualquer tipo de flutuar implementação apontam para um grau.

Leitura de dados binários brutos de endereço de memória de uma double não é portátil em tudo, e é obrigado a falhar em alguns implementação diferente.

Você pode usar de curso de um formato binário para compacidade, mas uma função C escrita portátil nesse formato não seria parecido com o trecho em tudo.

No mínimo, o código deve ser cercada por uma série de ifs / IFDEFs verificando que a representação da memória de doubles usados ??pela máquina atual corresponde exatamente o esperado pelo interpretador Python.

Escrevendo esse código seria difícil, que é por isso que eu estou sugerindo que a solução fácil, limpo, portátil e legível do texto ASCII.

Este seria minha definição de "melhor".

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top