PDA

Voir la version complète : lire un fichier par byte pour reconstruire des doubles


relativist
03/08/2005, 12h05
Bonjour a tutti;

Je voudrais lire un fichier byte par byte, et reconstruire des doubles a partir de ca. Voici le code que j'ai essayé dutiliser (et qui ne fonctionne pas,évidemment):

FileInputStream fis = new FileInputStream(Results);
ObjectInputStream in = new ObjectInputStream(fis);
byte[] buf = new byte[8];
int pos=0;
for(int j=0;j<=arrl;j++){
System.out.print(j);
t = Math.round(Math.round(Math.floor(j/(dim*dim*dim))));
m = Math.round(Math.round(Math.floor(j/(dim*dim)-t*dim)));
n = Math.round(Math.round(Math.floor((j/dim)-t*dim*dim-m*dim)));
o = j-t*dim*dim*dim-m*dim*dim-n*dim;
for (int i = 0; i<=3;i++) {
in.readFully(buf, pos,pos+8);
pos = pos+8;
X[m][n][o][t][i] = buf.doubleValue();}
for (int i = 0; i<=3;i++)
for (int k =0;k<=3;k++){
in.readFully(buf, pos,pos+8);
pos = pos+8;
met[m][n][o][t][i][k] = buf.doubleValue();}

Je sais que c'est de nouveau truffé de tableau a plein de dimension, mais le probleme n'est pas la. Le truc est que la méthode .doubleValue vient de l'objet Byte, et que je ne vois pas comment passer de byte[] à Byte.
Je ne suis pas sur non plus en ce qui concerne l'offset (variable pos). Est ce que readFully compte en bit ou en octet? (pour rappel, les double sont codés sur 8 octets)

J'implore donc encore votre grandeur d'ame et votre grand savoir...

Jny
03/08/2005, 13h05
J'ai trouvé ces méthodes dans la classe Byte, elles peuvent t'aider à transformer tes byte[i] en Byte :

static String toString(byte b) // Returns a new String object representing the specified byte.
static Byte valueOf(String s) // Returns a Byte object holding the value given by the specified String.

relativist
03/08/2005, 13h34
Attends, si g biensuivi ton idée, tu transforme les éléments de byte[] en chaines, puis tu concatene et tu retransforme en Byte... C'est pas con J'avais vu les méthodes sans penser a ce plan la.
En plus y a pas besoin de la méthode valueOf, il y a un constructeur de Byte(String s) qui marche direct avec les chaînes...

Ok ben c'est parti merci a toi et à tous les bretons de l'endroit (c'est un belge qui vous le dit :D )

relativist
04/08/2005, 10h48
OK j'ai trouvé la solution qui me parasitait la vie...
Passer les bytes sous forme de chaîne c'est foireux becoze il considère la valeurs chiffrées du bit avant de le mettre sous forme de chaine. apres la concatenation, on chope un truc rien a voir avec les doubles de départ.

Il faut en fait utiliser (et c'est nettement plus propre) un ByteBuffer. La classe définit des opérations put(bytes[]) et getDouble(). Il faut utiliser allocate(capacité du buffer) ou wrap(bytes[] qu'on met dedans) pour l'initialiser. Donc pour tout qui serait confronté a ce genre de truc ( au départ lire un fichier binaire écrit sous C++, le probleme etant que par sécurité les méthodes habituelles de Java incluent des header au fichier écrits et ne peuvent etre relus que par les methodes java correspondantes voyez la classe ObjectInputStream et ObjectOutputStream).

voici le code :

try {
FileInputStream fis = new FileInputStream(Results);
byte[] buf = new byte[8];
ByteBuffer buf2= ByteBuffer.allocate(8);

int pos=0;
for(int j=0;j<=arrl;j++){
System.out.print(j);
t = Math.round(Math.round(Math.floor(j/(dim*dim*dim))));
m = Math.round(Math.round(Math.floor(j/(dim*dim)-t*dim)));
n = Math.round(Math.round(Math.floor((j/dim)-t*dim*dim-m*dim)));
o = j-t*dim*dim*dim-m*dim*dim-n*dim;
for (int i = 0; i<=3;i++) {
fis.read(buf);
pos +=8;
buf2.position(0);
buf2.put(buf);
X[m][n][o][t][i] = buf2.getDouble(0);}
for (int i = 0; i<=3;i++)
for (int k =0;k<=3;k++){
fis.read(buf);
pos+=8;
buf2.position(0);
buf2.put(buf);
met[m][n][o][t][i][k] = buf2.getDouble(0);}

GeoView.scrtab[m][n][o][t] = met[m][n][o][t][1][1]-1;
}
fis.close();
}


Voili en esperant que ca puisse aider des gens (trop lourd de se taper la descripition des classes y en a trop ;.)

PS Attention en utilisant les Buffer, chaque opération change la position actuelle de lecture/écriture, il faut utiliser Buffer.position(new pos) pour regler tout ca...

relativist
04/08/2005, 12h32
Cela ne marche pas. C'est a dire que si ca marche mais ca ressort des chiffres debiles... Tout ca ,et je viens de m'en rendre compte est lié à la discussion précédente. En effet, C++ écrit ses fichiers en Little endian et java les lit en Big Endian (c'est l'ordre des bytes ) ---> probleme. La solution est toute fois donnée a dans la discussion "Big et Little Endian", il y a la l classes nécessaires et le code source. Finalement le code (le vrai le bon) tire cette gueule la :


try {
FileInputStream fis = new FileInputStream(Results);
int pos=timeStep*8*arrl*20 ;
fis.skip(pos);
for(int j=0;j<=arrl-1;j++){
m = Math.round(Math.round(Math.floor(j/(dim*dim))));
n = Math.round(Math.round(Math.floor((j/dim)-m*dim)));
o = j-m*dim*dim-n*dim;
for (int i = 0; i<=3;i++) {
X[m][n][o][i] = readDoubleLittleEndian(fis);
System.out.print(X[m][n][o][i]);}
for (int i = 0; i<=3;i++)
for (int k =0;k<=3;k++){
met[m][n][o][i][k] = readDoubleLittleEndian(fis);}
GeoView.scrtab[m][n][o] = met[m][n][o][1][1]-1;

}
fis.close();
}
public double readDoubleLittleEndian( FileInputStream fis)
{
int buf;
long accum = 0;
try{
for ( int shiftBy=0; shiftBy<64; shiftBy+=8 )
{
// must cast to long or shift done modulo 32
accum |= ( (long)( buf = fis.read() & 0xff ) ) << shiftBy;
}
return Double.longBitsToDouble( accum );
}
catch(IOException e){
System.out.print(e.toString());
return 0;
}
}


(A peu de chose pres parce que j'ai fait de la decoupe)

Voila desole pour les digressions...