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

Entrée/Sortie Java Discussion :

Tableau de short dans un RandomAccessFile ? (pb short -> byte)


Sujet :

Entrée/Sortie Java

  1. #1
    Membre averti
    Inscrit en
    Août 2005
    Messages
    29
    Détails du profil
    Informations forums :
    Inscription : Août 2005
    Messages : 29
    Par défaut Tableau de short dans un RandomAccessFile ? (pb short -> byte)
    Bonjour,

    Je veux mettre un tableau de milions de short dans un RandomAccessFile, de manière efficiente : donc pas short par short en utilisant .writeShort () sinon ça rame...

    Je trouve ça etrange qu'on puisse même pas utiliser de buffer (type BufferedOutputStream), avec RandomAccessFile, et que je sois obligé de convertir mon tableau de short en tableau de byte... je trouve ça quand même un peu préhistorique.
    (c'est le prof de java avec qui j'ai pris un cours ici en espagne qui m'a dit ça, mais si vous avez une autre idée, je suis prenneur !!)

    Bon, mon probleme est que le programme ci-dessous ne convertie pas bien les valeurs, il semble qu'il ait des erreurs de conversion short->byte ou bien byte->short, liées aux signes des valeurs... où est-ce que je me trompe ?

    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
    31
    32
    33
    34
    35
    36
    37
    38
    39
     
    ...
    short image [] = new short [3360000] ;
    short image2 [] = new short [3360000] ;
    byte buffer [] = new byte [3360000*2] ;
     
    ...
     
    //ecriture
     
    File testfile = new File("/MUSICA/sequence3") ;
    RandomAccessFile out = new RandomAccessFile (testfile,"rw") ;
     
    for (int i = 0; i < image.length; ++i) {
    	// convertion short -> byte
    	buffer [i*2] =  (byte) ( (image[i]) >> 8 ) ;   // le probleme doit 
    	buffer [i*2+1] = (byte) ( (image[i]) % 256 );  // etre ici...
    }
    out.seek(0)  ;
    out.write(buffer);
    out.close();
     
    ...
     
    //lecture
     
    File testfile = new File("/MUSICA/sequence3") ;
    RandomAccessFile in = new RandomAccessFile (testfile,"r") ;
     
    in.seek(0);
    in.read(buffer);
    in.close();			
    for (int i = 0; i < image2.length; ++i) {
    	// convertion byte -> short
    	image2[i] = (short) ( ( (((short)buffer [i*2]) << 8 ) | ((short)buffer [i*2+1]) )  ) ;
    	// ...ou bien le probleme peut etre là ...
    }
     
    ...

  2. #2
    Membre Expert Avatar de Uther
    Homme Profil pro
    Tourneur Fraiseur
    Inscrit en
    Avril 2002
    Messages
    4 697
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Pyrénées Orientales (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Tourneur Fraiseur

    Informations forums :
    Inscription : Avril 2002
    Messages : 4 697
    Par défaut
    En effet pour éviter les problème de signe, il vaut mieux utiliser l'opérateur binaire & que un modulo pour ce genre de problème:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    for (int i = 0; i < image.length; ++i) {
    	buffer [i*2] =  (byte) ( (image[i]) >> 8 ) ;   // le problème doit 
    	buffer [i*2+1] = (byte) ( (image[i]) & 0xFF );  // être ici...
    }
    De plus fais attention pour savoir si tes nombres doivent être stocké dans le fichier sous forme Big Endian (0x1234 est stocké sous forme de 0x12 puis 0x34) ou Little Endian(0x1234 est stocké sous forme de 0x34 puis 0x12). Java stocke toujours en Big Endian quelque soit la plateforme, tandis que dans la plupart des langages comme le C, cela dépend de la plateforme (Little Endian sur les processeurs de type intel, Big Endian pour les processeurs de type Power PC)

  3. #3
    Membre Expert
    Homme Profil pro
    Dév. Java & C#
    Inscrit en
    Octobre 2002
    Messages
    1 414
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Suisse

    Informations professionnelles :
    Activité : Dév. Java & C#
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Octobre 2002
    Messages : 1 414
    Par défaut
    Bonjour,

    Il me semble que j'avais déjà donné une solution ou un début de solution à ce problème.

    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
    31
    32
    33
    34
    35
    36
    37
    38
    39
     
    short image [] = new short [3360000] ;
    short image2 [] = new short [3360000] ;
    /* La valeur de bufferSize est à choisir en fonction du système ou par des essais. */
    final bufferSize = 36 * 1024; 
    ...
     
    //ecriture
     
    final File testfile = new File("/MUSICA/sequence3") ;
    final DataOutputStream out = new DataOutputStream(new BufferedOutputStream(new FileOutputStream(testfile), bufferSize );
     
    for (int i = 0; i < image.length; ++i) {
      out.writeShort(imge[i]);	
    }
    out.flush();
    out.close();
     
    ...
     
    //lecture
    final DataInputStream in = new DataInputStream(new BufferedInputStream(new FileInputStream(testfile), bufferSize);
    boolean eof = false;			
    try {
      for (int i = 0;;++i) {
        buffer[i] = in.readShort();
      }
    }
    catch(EOFExecption eof) {
      eof = true;
    }
    catch(IOExecption ioe) {
      ioe.printStackTrace(System.err);
    }
    if (!eof) {
      System.err.println("Une errreur s'est produite durant la lecture");
    }
    in.close(); 
    ...
    !!!! Code non compilé et donc non testé !!!!

  4. #4
    Membre averti
    Inscrit en
    Août 2005
    Messages
    29
    Détails du profil
    Informations forums :
    Inscription : Août 2005
    Messages : 29
    Par défaut
    jowo, merci pour ton code mais tu te trompe, ce n'est pas le même problème que la dernière fois, j'ai ici besoin de RandomAccessFile (car j'ai besoin d'un accès dynamique à mes fichiers, et d'après ce qu'on m'a dit, RandomAccessFile ne permet pas, étrangement, d'utiliser de buffer.)

    Uther, merci pour tes indications mais même avec "& 0xFF", le code ne marche toujours pas, il y a toujours un problème de conversion. J'ai refais un code plus simple pour voir :
    (ça marche jusqu'à 127, puis 128 donne -128, 129 donne -127, 130 donne -126, ...)

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
     
    byte big =  (byte) ( (valueshort) >> 8 ) ;
    byte small = (byte) ( (valueshort) & 0xFF  );
     
    short result = (short) ( ( big << 8 ) | small ) ;

    comment faire pour que "result" soit égal à "valueshort" ??



    Et en fait, je trouve ça incroyable d'être obliger de faire tout ça pour simplement mettre un tableau numérique dans un fichier en accès direct. !?!
    1 - d'une part, que l'accès direct ne permette pas l'utilisation de buffer !?!
    2 - d'autre part, qu'il n'existe pas de méthode pour faire ces conversions sans triturer les bits à la main !?!

    Java est quand même un langage mature, non ?

  5. #5
    Membre Expert Avatar de Uther
    Homme Profil pro
    Tourneur Fraiseur
    Inscrit en
    Avril 2002
    Messages
    4 697
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Pyrénées Orientales (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Tourneur Fraiseur

    Informations forums :
    Inscription : Avril 2002
    Messages : 4 697
    Par défaut
    jowo, merci pour ton code mais tu te trompe, ce n'est pas le même problème que la dernière fois, j'ai ici besoin de RandomAccessFile (car j'ai besoin d'un accès dynamique à mes fichiers, et d'après ce qu'on m'a dit, RandomAccessFile ne permet pas, étrangement, d'utiliser de buffer.)
    En effet, RandomAccessFile ne marche pas comme un flux donc pas de BufferedInputStream. Cependant, tu peux peut-être ta contenter d'un BufferedInputStream et de la méthode skip().
    Par contre si tu veux lire et ecrire en même temps ou le placer facilement a n'importe quel point, il faudra en effet te contenter de RandomAccesFile.

    Uther, merci pour tes indications mais même avec "& 0xFF", le code ne marche toujours pas, il y a toujours un problème de conversion. J'ai refais un code plus simple pour voir :
    (ça marche jusqu'à 127, puis 128 donne -128, 129 donne -127, 130 donne -126, ...)
    En effet, je n'avais pas lu ton code jusqu'au bout. Il y a aussi le problème inverse à la récupération du résultat.
    En java, les calculs ne se font jamais directement sur les byte, char, ou short. Ils sont d'abord convertis en int en tenant compte du signe.
    La encore la solution est le &:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    short result = (short) ( ( big << 8 )&0xFF00 | small&0x00FF ) ;
    Et en fait, je trouve ça incroyable d'être obliger de faire tout ça pour simplement mettre un tableau numérique dans un fichier en accès direct. !?!
    1 - d'une part, que l'accès direct ne permette pas l'utilisation de buffer !?!
    2 - d'autre part, qu'il n'existe pas de méthode pour faire ces conversions sans triturer les bits à la main !?!
    1- Il le permet pour les bytes, ce qui est l'usage le plus courant au fond.
    2- Java n'a clairement pas été prévu pour rendre plus efficae les manipulation de sur les types primitifs, même s'il ne les renie pas totalement contrairement a certain langages qui se veulent purement objet.
    Il a préféré une approche simplifié par rapport au C (tout signé, conversion auto en int). C'est déroutant mais quant on a compris le principe, ce n'est pas si compliqué que ça.

  6. #6
    Membre averti
    Inscrit en
    Août 2005
    Messages
    29
    Détails du profil
    Informations forums :
    Inscription : Août 2005
    Messages : 29
    Par défaut
    merci chef, là tu m'éclaire !
    maintenant ça marche et je prend note de toutes tes remarques..

    Il le permet pour les bytes, ce qui est l'usage le plus courant au fond.
    l'usage le plus courant ? byte ? alors que les valeurs numériques sont traditionnellement en int ?

  7. #7
    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
    je rajouterais que, pour les performances, il y a toutes la api nio, qui permettent de mapper des bout du fichier en mémoire en utilisant des mapping système, tout en permettant l'accès relativement aléatoire.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    byte[] data=.....;
    RandomAccessFile out = new RandomAccessFile (testfile,"rw") ;
    FileChannel channel = out.getChannel();
    MappedByteBuffer buffer = channel.map(FileChannel.MapMode.READ_WRITE, debut, tailleDeBuffer);
    buffer.put(69,aByte); // ecrit aByte dans le fichier à l'offset debut+69
    buffer.put(data,12,59); // ecrit 59 byte depuis l'offset 12 de data dans le fichier à la position debut et incrémente la position courante de 59
    buffer.put(aByte); // ecrit aByte dans le fichier à la position debut+59

  8. #8
    Membre averti
    Inscrit en
    Août 2005
    Messages
    29
    Détails du profil
    Informations forums :
    Inscription : Août 2005
    Messages : 29
    Par défaut
    Merci pour cet api nio. j'y regarderai plus avant si jamais j'en ai besoin. Mais pour l'instant je vais me contenter de mon code qui fonctionne, vu que je suis encore relativement novice.

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

Discussions similaires

  1. conversion int -> short dans une méthode(short)
    Par 0redd dans le forum Débuter avec Java
    Réponses: 9
    Dernier message: 24/08/2010, 06h50
  2. Réponses: 5
    Dernier message: 22/03/2006, 13h25
  3. Ranger un tableau de String dans ma HashMap
    Par jeyce dans le forum Collection et Stream
    Réponses: 3
    Dernier message: 26/08/2004, 22h41
  4. Tableau de vertex dans OpenGL
    Par Guizmo57 dans le forum OpenGL
    Réponses: 5
    Dernier message: 11/04/2004, 09h15
  5. [Kylix] stockage d'un tableau d'octets dans interbase
    Par georges1001 dans le forum EDI
    Réponses: 1
    Dernier message: 16/09/2003, 14h14

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