IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Langage Java Discussion :

Lecture erronée de float dans un fichier binaire


Sujet :

Langage Java

  1. #1
    Membre averti
    Profil pro
    Inscrit en
    Janvier 2006
    Messages
    42
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Janvier 2006
    Messages : 42
    Par défaut Lecture erronée de float dans un fichier binaire
    Bonjour,

    J'ai un fichier binaire contenant des float que je peux lire sans problème avec le code C++ suivant:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
     
    template<typename T>
    std::istream & read(std::istream& is, T& value) {
        return is.read(reinterpret_cast<char*> (&value), sizeof (T));
    }
     
    int main(int argc, char** argv) {
     
        std::ifstream FileIn("conc1.out", std::ios_base::binary);
        float xin;
        for (int i = 0; i < 2230; i++) {
            read(FileIn, xin);
            std::cout << xin << " ";
        }
        cout << endl;
        FileIn.close();
     
        return 0;
    }
    J'ai le code suivant en JAVA:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
     
        public static void main(String[] args) {
            // TODO code application logic here
            FileInputStream fis = null;
            try {
                fis = new FileInputStream("Y:\\Hydrus_2D\\ONDRAF_2D_safety_model\\Boundary_conditions\\Flow\\average\\conc1.out");
                DataInputStream dis = new DataInputStream(fis);
                try {
                    for (int i = 0; i < 2230; i++) {
                        System.out.print(Float.intBitsToFloat(dis.readInt()) + " ");
                        if (i % 100 == 0) {
                            System.out.println();
                        }
                    }
                } finally {
                    if (fis != null) {
                        fis.close();
                    }
                }
            } catch (IOException ioe) {
                System.out.println("IOException");
            }
        }
    Et je n'obtiens pas les valeurs numériques escomptées alors que le code C++ fonctionne sans problème.

    Avez-vous une solution?

    Cordialement,

    Bou

  2. #2
    Rédacteur
    Avatar de bulbo
    Homme Profil pro
    Consultant informatique
    Inscrit en
    Février 2004
    Messages
    1 259
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : France

    Informations professionnelles :
    Activité : Consultant informatique
    Secteur : Finance

    Informations forums :
    Inscription : Février 2004
    Messages : 1 259
    Par défaut
    Bonjour,

    J'attire ton attention sur un petit point de la javadoc de DataInputStream.

    Citation Envoyé par javadoc
    A data input stream lets an application read primitive Java data types from an underlying input stream in a machine-independent way
    Ce qui veut dire que java se débrouille pour toujours écrire/lire les données de la même manière peu importe que le processeur utilise du BigEndian ou du littleEndian.

    Le code C++ lui se contente d'utiliser la convention de ta plate forme pour lire les floats quand le code java lui s'attend à trouver toujours la même convention (là tout de suite je ne sais plus qu'elle convention utilise java pour ça: little ou big ??).

    Donc si ta machine n'a pas la même convention et que les fichiers ont été crée depuis une appli C++ par exemple, java ne sera pas capable de lire correctement tes floats.

    La seule solution qui s'offre à toi si une telle interaction est nécessaire, c'est de lire les données byte par byte et pas directement int par int .. d'ailleurs pourquoi n'avoir pas fait directement un readFloat sur le DataInputStream ?

    Et ensuite il va te falloir reconstituer un int à partir des byte remis dans l'ordre correct et transformer ce int en float comme le fait déjà ton programme.

    Bonne chance,

    Bulbo
    [Java] [NetBeans] [CVS]
    La FAQ Java
    Merci de ne pas me poser de questions techniques par MP.

  3. #3
    Membre averti
    Profil pro
    Inscrit en
    Janvier 2006
    Messages
    42
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Janvier 2006
    Messages : 42
    Par défaut
    Merci pour ta réponse, j'ai essayé tes suggestions et je n'y arrive toujours pas.
    J'ai essayé ça:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
     
      public static int toInt(byte[] bytes) {
            int result = 0;
            for (int i = 0; i < 4; i++) {
                result = (result << 8) - Byte.MIN_VALUE + (int) bytes[i];
            }
            return result;
        }
     
    ....
     
     
     byte[] b = new byte[4];
                        dis.read(b);
                        System.out.print(toInt(b)+" ");
                        //System.out.print(Float.intBitsToFloat(dis.readInt()) + " ");
                        //System.out.print(dis.readFloat() + " ");
    As-tu une suggestion?

  4. #4
    Expert éminent
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 482
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 482
    Par défaut
    tout d'abord, tes floats, dans ton fichiers, ils sont dans quel format? 32 bits je suppose, mais little endian ou bg endian? Je suppose qu'il s'agit d'une machine utilisant le formattage IEEE ?


    une fois que tu aura l'endiance, tu devra lire 4 byte de l'inputstream (pas le datainputstream!), les mettre dans le bon ordre pour reconstituer le int et enfin le passer à la méthode.

    PS: ta formule byte[] -> int ne m'a pas l'air d'avoir beaucoup de sens :/

  5. #5
    Rédacteur
    Avatar de bulbo
    Homme Profil pro
    Consultant informatique
    Inscrit en
    Février 2004
    Messages
    1 259
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : France

    Informations professionnelles :
    Activité : Consultant informatique
    Secteur : Finance

    Informations forums :
    Inscription : Février 2004
    Messages : 1 259
    Par défaut
    Heu je ne vois pas bien ce que tu essayes de faire dans ton toInt().

    Essaye plutôt ça

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    int result = ((bytes[0] & 0xFF) << 24) | (((bytes[1] & 0xFF) << 16) | (((bytes[2] & 0xFF) << 8) | ((bytes[3] & 0xFF);
    tu devrais obtenir un meilleur résultat je pense.

    Bulbo
    [Java] [NetBeans] [CVS]
    La FAQ Java
    Merci de ne pas me poser de questions techniques par MP.

  6. #6
    Expert éminent
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 482
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 482
    Par défaut
    ou ça

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    int result = ((bytes[3] & 0xFF) << 24) | (((bytes[2] & 0xFF) << 16) | (((bytes[1] & 0xFF) << 8) | ((bytes[0] & 0xFF);
    suivant l'endiance

  7. #7
    Rédacteur
    Avatar de bulbo
    Homme Profil pro
    Consultant informatique
    Inscrit en
    Février 2004
    Messages
    1 259
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : France

    Informations professionnelles :
    Activité : Consultant informatique
    Secteur : Finance

    Informations forums :
    Inscription : Février 2004
    Messages : 1 259
    Par défaut
    Citation Envoyé par tchize_ Voir le message
    ou ça

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    int result = ((bytes[3] & 0xFF) << 24) | (((bytes[2] & 0xFF) << 16) | (((bytes[1] & 0xFF) << 8) | ((bytes[0] & 0xFF);
    suivant l'endiance
    D'après le prédicat de départ, java n'utilise pas la même endiance que celle utilisé pour créer ses fichiers binaires.

    Le code que tu nous montre là ne change en rien l'endiance du fichier, du coup ça ne marche pas dans son cas particulier et surtout on se simplifierait singulièrement la vie avec un readFloat sur le DataInputStream..

    Maintenant c'est sur que le code qu'on lui passe là ne fonctionnera que sur des binaires ne correspondant pas à l'endiance qu'utilise java pour lire des flux binaires.

    Bulbo
    [Java] [NetBeans] [CVS]
    La FAQ Java
    Merci de ne pas me poser de questions techniques par MP.

  8. #8
    Expert éminent
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 482
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 482
    Par défaut
    bulbo: non, c'est ton code qui lit un int de la même manière que DataInput.readInt


    Reads four input bytes and returns an int value. Let a-d be the first through fourth bytes read. The value returned is:


    (((a & 0xff) << 24) | ((b & 0xff) << 16) |
    ((c & 0xff) << 8) | (d & 0xff))
    avec a=byte[0] dans ton code et d=byte[3]

  9. #9
    Rédacteur
    Avatar de bulbo
    Homme Profil pro
    Consultant informatique
    Inscrit en
    Février 2004
    Messages
    1 259
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : France

    Informations professionnelles :
    Activité : Consultant informatique
    Secteur : Finance

    Informations forums :
    Inscription : Février 2004
    Messages : 1 259
    Par défaut
    Citation Envoyé par tchize_ Voir le message
    bulbo: non, c'est ton code qui lit un int de la même manière que DataInput.readInt




    avec a=byte[0] dans ton code et d=byte[3]
    oups.. enfin tu m'as rectifié, tant mieux

    Bulbo
    [Java] [NetBeans] [CVS]
    La FAQ Java
    Merci de ne pas me poser de questions techniques par MP.

  10. #10
    Membre averti
    Profil pro
    Inscrit en
    Janvier 2006
    Messages
    42
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Janvier 2006
    Messages : 42
    Par défaut Solution
    Merci à tous pour vos réponses. J'ai fait ceci et tout fonctionne à merveille:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
     
      FileInputStream fis = null;
            try {
                fis = new FileInputStream("Y:\\Hydrus_2D\\ONDRAF_2D_safety_model\\Boundary_conditions\\Flow\\average\\conc1.out");
                DataInputStream dis = new DataInputStream(fis);
                try {
                    for (int i = 0; i < 2230; i++) {
                        byte[] bytes = new byte[4];
                        dis.read(bytes);
                        int asInt = (bytes[0] & 0xFF)
                                | ((bytes[1] & 0xFF) << 8)
                                | ((bytes[2] & 0xFF) << 16)
                                | ((bytes[3] & 0xFF) << 24);
                        float asFloat = Float.intBitsToFloat(asInt);
     
                        System.out.print(asFloat + " ");
                        //System.out.print(Float.intBitsToFloat(dis.readInt()) + " ");
                        //System.out.print(dis.readFloat() + " ");
                        if (i % 100 == 0) {
                            System.out.println();
                        }
                    }
                } finally {
                    if (fis != null) {
                        fis.close();
                    }
                }
            } catch (IOException ioe) {
                System.out.println("IOException");
            }
    Merci encore à tous pour votre dévouement.

    Bou

  11. #11
    Membre Expert
    Avatar de professeur shadoko
    Homme Profil pro
    retraité nostalgique Java SE
    Inscrit en
    Juillet 2006
    Messages
    1 257
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 76
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : retraité nostalgique Java SE

    Informations forums :
    Inscription : Juillet 2006
    Messages : 1 257
    Par défaut
    autre solution pour pas réinventer la roue: utiliser java.nio pour les E/S
    (il faut y penser dès qu'on a un protocole avec des données "non Java")

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. [Débutant] C# sous Win8, lecture dans un fichier binaire en asynchrone
    Par yupa dans le forum C#
    Réponses: 2
    Dernier message: 14/06/2012, 14h35
  2. Lecture dans un fichier binaire
    Par crashtib dans le forum C
    Réponses: 3
    Dernier message: 28/05/2009, 15h13
  3. Lecture formattée dans un fichier binaire
    Par YéTeeh dans le forum C++
    Réponses: 5
    Dernier message: 16/12/2007, 21h35
  4. Lecture ecriture dans un fichier binaire
    Par laetous dans le forum C
    Réponses: 13
    Dernier message: 26/08/2006, 08h50
  5. [LG]ecriture dans un fichier binaire
    Par jsaviola dans le forum Langage
    Réponses: 3
    Dernier message: 26/12/2003, 17h30

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo