lecture de binaires (c vers java)

thesuixx
lecture de binaires (c vers java)

Bonjour,
je travaille actuellement sur une chaine de traitement dont une composante (écrite en c) effectue la lecture d'un fichier binaire et en extrait des valeurs double à partir de 2 octets,
je vous mets une version simplifiée ici (normalement, les valeurs sont écrites dans une matrice de valeurs, les variables globales ont été initialisés avec des valeurs bidons pour les tests: Coeffp = 0.01 et nbLus = 200):

/** remplit le tableau PLUIE1 avec les valeurs presentes dans le tableau
  * en les multipliant avec le coefficient defini par la variable CoeffP
  * @param filLu : flux du fichier
  */
int remplirPLUIE1(FILE* filLu){
    int i=0, j=0;
    unsigned short valLu;
    char *val = (char *)calloc( sizeof(unsigned short)+1, sizeof(char));
    float valeur;
	
	printf("    CoeffP == %f\n",CoeffP);
	
	
    /* Parcours du fichier en lecture */
    rewind (filLu);
    fread(&valLu, sizeof(unsigned short), 1, filLu);
    
        for(i=0; i<nbLus && !feof(filLu); i++){
			sprintf(val, "%d", valLu);           // on prend la valeur sur 2 octets  
			
			valeur = atoi(val)*CoeffP;           // le coeff est en flottant
            printf("%f\n",valeur);               // on affiche

            fread(&valLu, sizeof(unsigned short), 1, filLu);
        }

    return 0;
}

le probleme, c'est que je voudrais faire cette lecture dans le programme principal (java)
j'ai donc fait quelques petits tests comme par exemple:
 /**
     * effectue la lecture d'un fichier binaire et extrait les données dans une Observation
     * @param fichierBinaire: l'uri du fichier binaire
     * @return une Observation
     */
    public static void lireFichierBinaire(String fichierBinaire) {
        DataInputStream in = null;


        System.out.println("    lecture du fichier binaire " + fichierBinaire);
        System.out.println("    CoeffP == " + CoeffP);
        System.out.println("    lireFichierBinaire");

        try {
            // on crée un input stream de bytes
            in = new DataInputStream(new FileInputStream(fichierBinaire));


            // le compteur (sert à se reperer dans la liste des capteurs)
            int compteur = 0;
            char c;
            // on lit les octets 2 par 2
            while (compteur < nbLus && (c = in.readChar()) != -1) {
                System.out.println("" + ((double) (int)c * CoeffP));
                compteur++;
            }
        } catch (IOException ex) {
            System.out.println(ex);
        } finally {
            try {
                if (in != null) {
                    in.close();
                }
            } catch (IOException ex) {
                System.out.println(ex);
            }
        }
    }

mais les resultats ne concordent pas, savez vous par hasard quelles modifications sont à apporter à cette fonction pour que ca marche ?
j'ai aussi essayé ca:
    /**
     * effectue la lecture d'un fichier binaire et extrait les données dans une Observation
     * @param fichierBinaire: l'uri du fichier binaire
     * @return une Observation
     */
    public static void lireFichierBinaire2(String fichierBinaire) {
        DataInputStream in = null;


        System.out.println("    lecture du fichier binaire " + fichierBinaire);
        System.out.println("    CoeffP == " + CoeffP);
        System.out.println("    unsignedByteToInt1");
        
        try {
            // on crée un input stream de bytes
            in = new DataInputStream(new FileInputStream(fichierBinaire));

            byte[] byteArray = new byte[2];

            // le compteur (sert à se reperer dans la liste des capteurs)
            int compteur = 0;

            // on lit les octets 2 par 2
            while (compteur < nbLus && in.read(byteArray) != -1) {
                System.out.println("" + ((double) byteArrayToInt(byteArray) * CoeffP));
                compteur++;
            }
        } catch (IOException ex) {
            System.out.println(ex);
        } finally {
            try {
                if (in != null) {
                    in.close();
                }
            } catch (IOException ex) {
                System.out.println(ex);
            }
        }
    }

    private static int byteArrayToInt(byte[] byteArray) {
        int total = 0;
//        for (int i = 0; i < byteArray.length; i++) {
//            total += ((byteArray.length - i) * 255) * byteArray[i] / 255;
//        }

//        total = byteArray[0] * byteArray[1];
        
        int a = unsignedByteToInt(byteArray[0]);
        int b = unsignedByteToInt(byteArray[1]);
        
        
        System.out.print(""+byteArray[0]+" "+byteArray[1]+" "+a+" "+b+" >> ");
        
//        total = a*255 + b;
        total = byteArray[0] * byteArray[1];
        
        return total;
    }
    
    /**
     * effectue la conversion d'un byte en int en traitant le byte comme unsigned
     * @param b
     * @return
     */
    private static int unsignedByteToInt(byte b){
        int res = (int)b;
        if (res < 0){
            res = 128 + (128 + res);  // voir complément à deux
        }
        return res;
    }

mais les résultats sont également erronés par rapport aux résultats obtenus avec la focntion c...

les fonctions tests ainsi qu'un fichier binaire sont accesibles ici:
[url]
http://benjbb3sp.free.fr/lecture%20binaire/
[/url]

fredericmazue

Je n'ai pas lu ton code, mais as tu pensé que très probablement les valeurs sont codées en little endian en C et que de son côté, Java code en Big endian ?

thesuixx

effectivement, les fichiers binaires étaient encodés en little endian, alors que la jvm ne traite que du big endian, en faisant quelques petits bidouillages, j'ai reussi à résoudre mon probleme
voila ce que ca donne:

        public static final float CoeffP = 0.01f;
    public static final int nbLus = 200;

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        if (args.length > 0) {
            System.out.println("start");
            lireFichierBinaire(args[0]);
            System.out.println("The End");
        } else {
            System.out.println("Not Enough arguments");
        }
    }

    /**
     * fonction test de lecture d'un fichier .dat
     * @param fichierBinaire: l'uri du fichier binaire
     */
    public static void lireFichierBinaire(String fichierBinaire) {
        DataInputStream in = null;

        System.out.println("    lecture du fichier binaire " + fichierBinaire);
        System.out.println("    CoeffP == " + CoeffP);
        
        try {
            // on crée un input stream de bytes
            in = new DataInputStream(new FileInputStream(fichierBinaire));

            byte[] byteArray = new byte[2];

            // le compteur (sert à se reperer dans la liste des capteurs)
            int compteur = 0;

            // on lit les octets 2 par 2
            while (compteur < nbLus && in.read(byteArray) != -1) {
                System.out.println("" + ((double) byteArrayToInt(byteArray) * CoeffP));
                compteur++;
            }
        } catch (IOException ex) {
            System.out.println(ex);
        } finally {
            try {
                if (in != null) {
                    in.close();
                }
            } catch (IOException ex) {
                System.out.println(ex);
            }
        }
    }

    /**
     * extrait la valeur int d'un byte array en little endian
     * @param byteArray: un byte array en ordre little endian
     * @return int
     */
    private static int byteArrayToInt(byte[] byteArray) {
        int total = 0;
        for (int i = 0; i < byteArray.length; i++) {
            total += unsignedByteToInt(byteArray[i]) * ((i*256) == 0 ? 1 : i*256);
        }
        return total;
    }
    
    /**
     * effectue la conversion d'un byte en int en traitant le byte comme s'il était unsigned
     * @param b: le byte
     * @return la valeur int du byte comme s'il était unsigned
     */
    private static int unsignedByteToInt(byte b){
        int res = (int)b;
        if (res < 0){
            res = 256 + res;  // voir complément à deux
        }
        return res;
    }
   

et ici deux (parties de ) traces de l'exectution du programme test en c et de celui ci avec le même fichier binaire en parametre

start
    Lecture du fichier binaire pd04-199409212054.dat
    CoeffP == 0.010000
0.000000
0.000000
0.000000
0.000000
5.040000
5.040000
0.000000
0.000000
0.000000
0.000000

start
    lecture du fichier binaire pd04-199409212054.dat
    CoeffP == 0.01
0.0
0.0
0.0
0.0
5.039999887347221
5.039999887347221
0.0
0.0
0.0
0.0

j'ai un petit décalage de valeur mais ce n'est pas tres genant vu que ce sont des valeurs millimetres