2009-03-10 8 views
5

Un programme C crache des doubles consécutifs dans un fichier binaire. Je souhaite les lire en Python. J'ai essayé d'utiliser struct.unpack('d',f.read(8))Quelle est la meilleure méthode pour lire un double à partir d'un fichier binaire créé en C?

EDIT: je les éléments suivants en C pour écrire un nombre aléatoire à double

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

Les erreurs sont maintenant fixés mais je ne peux pas lire la première valeur. pour un tout 0.000 .. nombre il le lit comme 3.90798504668055 mais le reste est bien.

+0

Il peut être connecté avec un caractère incorrect (ce qui vient en premier, c'est l'octet le moins significatif ou non). Montrez les octets que vous essayez de lire. – jfs

+0

Je suis désolé. J'ai presque corrigé le problème, donc j'ai marqué la réponse. J'aimerais voir le premier numéro lu correctement. – gnosio

+0

Pouvez-vous fournir une sauvegarde des 40 premiers octets du fichier avec le code que vous utilisez actuellement pour le lire? –

Répondre

3

Je pense que vous lisez en fait le bon numéro, mais sont vous sentir désorienté affichage. Lorsque je lis le numéro de votre fichier fourni, je reçois "3.907985046680551e-14" - c'est presque mais pas tout à fait zéro (0.000000000000039 sous forme développée). Je soupçonne que votre code C est en train de l'imprimer avec moins de précision que python. [Edit] Je viens d'essayer de lire le fichier en C, et j'obtiens le même résultat (bien que légèrement moins précis: 3.90799e-14) (en utilisant printf ("% g", val)), donc je pense que si cette valeur est incorrecte, c'est arrivé du côté de l'écriture, plutôt que de la lecture.

+0

Hey Brian, vous l'avez cloué. J'étais paresseux pour l'agrandir :(La précision est la raison de 2 valeurs différentes Merci pour l'aide. – gnosio

1

Pourriez-vous élaborer sur "n'a pas fonctionné"? La commande s'est-elle écrasée? Les données ont-elles été erronées? Qu'est-ce qui s'est réellement passé?

Si la commande est écrasé:

  • S'il vous plaît partager la sortie d'erreur de la commande

Si les données simplement sorti mal:

  • -ce que les systèmes qui créent et lire les données ont la même endianness? Si l'un est big-endian, et l'autre est little-endian, alors vous devez spécifier une conversion endianness dans votre chaîne de format.

  • Si l'endianness des deux ordinateurs sont les mêmes, comment les données ont-elles été écrites dans le fichier, exactement? Savez-vous? Si vous le faites, quelle est la valeur écrite dans le fichier et quelle est la valeur incorrecte que vous avez obtenue?

0
  • f.read(8) pourrait revenir à moins de 8 octets
  • données peuvent avoir un alignement différent et/ou boutisme:

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

La meilleure méthode serait d'utiliser un Fichier texte ASCII:

0,0
3,1416
3,90798504668055

en ce qu'il serait portable et travailler avec tout type de mise en œuvre flottante point à un degré.

La lecture de données binaires brutes à partir d'une adresse mémoire de double n'est pas portable du tout et risque d'échouer dans une implémentation différente.

Vous pouvez bien sûr utiliser un format binaire pour la compacité, mais une fonction C portable qui écrit dans ce format ne ressemblerait pas du tout à votre extrait de code. À tout le moins, le code doit être entouré d'une série de ifs/ifdefs vérifiant que la représentation en mémoire de double s utilisée par la machine actuelle correspond exactement à celle attendue par l'interpréteur Python.

Écrire un tel code serait difficile, c'est pourquoi je suggère la solution facile, propre, portable et lisible par l'homme du texte ASCII.

Ce serait ma définition de "meilleur".

+0

Salut Aib, je voudrais pouvoir le faire mais c'est un vidage de la mémoire et je n'ai pas contrôle sur la façon dont il est exporté. Je vais avoir un bon succès avec le déballage mais pour une raison quelconque ne lit pas correctement le premier Double. – gnosio

+0

Je l'ai deviné, mais je voulais toujours faire valoir mon point de vue pour les futurs lecteurs. Je suis content que tu aies résolu ton problème. – aib

1

D'abord, avez-vous essayé pickle? Personne n'a montré aucun code Python encore ... Voici un code pour la lecture en binaire 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() 

Lorsque le f ici spécifié simple précision, 4 octets flottants, numéros. Trouvez la taille de vos données par entrée et utilisez-la.

Pour les données non binaires que vous pourriez faire quelque chose de simple comme ceci:

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

Hey Alex, j'ai essayé le cornichon mais pour mon problème je ne suis pas garanti de toutes les valeurs pour être en double. Ils pourraient être Ints, flotteurs ou doubles. Tout ce que je sais, c'est l'emplacement et le type de valeur à lire. Merci pour l'aide cependant :) – gnosio

Questions connexes