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 :

Manipuler les bits


Sujet :

Entrée/Sortie Java

  1. #1
    Membre confirmé Avatar de fomazou
    Inscrit en
    Mars 2004
    Messages
    220
    Détails du profil
    Informations forums :
    Inscription : Mars 2004
    Messages : 220
    Par défaut Manipuler les bits
    comment puis-je pour manipuler les bits.
    je pouvoir lir un fichier lire les caractères et mettre le bits (correspondants) dans un tableau!

  2. #2
    Membre Expert
    Profil pro
    Fabrication GED
    Inscrit en
    Octobre 2005
    Messages
    1 405
    Détails du profil
    Informations personnelles :
    Âge : 46
    Localisation : France, Seine Maritime (Haute Normandie)

    Informations professionnelles :
    Activité : Fabrication GED

    Informations forums :
    Inscription : Octobre 2005
    Messages : 1 405
    Par défaut
    va falloir être plus précis, tu parles de caractères or un caractère peut être codé sur un nombre différent de bit (selon l'encodage). Ensuite tu veux mettre des bits dans un tableau, sous quelle forme ?

  3. #3
    Membre expérimenté Avatar de jibbi
    Profil pro
    Inscrit en
    Avril 2007
    Messages
    165
    Détails du profil
    Informations personnelles :
    Âge : 49
    Localisation : France

    Informations forums :
    Inscription : Avril 2007
    Messages : 165
    Par défaut
    Salut

    On peut faire ca avec un ByteArrayInputStream

  4. #4
    Membre chevronné
    Profil pro
    Inscrit en
    Octobre 2007
    Messages
    442
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2007
    Messages : 442
    Par défaut
    Voili voilou :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    public byte[] getBytes(String filepath) throws IOException
    {
        FileInputStream in = new FileInputStream(new File(filepath));
        byte[] b = new byte[in.available()];
        in.read(b);
        in.close();
        return b;
    }

  5. #5
    Membre Expert
    Profil pro
    Fabrication GED
    Inscrit en
    Octobre 2005
    Messages
    1 405
    Détails du profil
    Informations personnelles :
    Âge : 46
    Localisation : France, Seine Maritime (Haute Normandie)

    Informations professionnelles :
    Activité : Fabrication GED

    Informations forums :
    Inscription : Octobre 2005
    Messages : 1 405
    Par défaut
    Citation Envoyé par Duc Lebowski Voir le message
    Voili voilou :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    public byte[] getBytes(String filepath) throws IOException
    {
        FileInputStream in = new FileInputStream(new File(filepath));
        byte[] b = new byte[in.available()];
        in.read(b);
        in.close();
        return b;
    }
    heu, il se passe quoi si le fichier fait 4Go ?

  6. #6
    Membre chevronné
    Profil pro
    Inscrit en
    Octobre 2007
    Messages
    442
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2007
    Messages : 442
    Par défaut
    Citation Envoyé par iohack Voir le message
    heu, il se passe quoi si le fichier fait 4Go ?
    Réponse 1 : et il se passe quoi si des extraterrestres lancent une cyber-attaque sur la terre ?

    Réponse 2 : t'as plus de place sur ton disque dur !

    Réponse 3 : si tu as 10 Go de RAM tout va pour le mieux !

    fomazou, quelle taille fait ton fichier ?

  7. #7
    Expert éminent
    Avatar de adiGuba
    Homme Profil pro
    Développeur Java/Web
    Inscrit en
    Avril 2002
    Messages
    13 938
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Java/Web
    Secteur : Transports

    Informations forums :
    Inscription : Avril 2002
    Messages : 13 938
    Billets dans le blog
    1
    Par défaut
    Salut,

    Citation Envoyé par iohack Voir le message
    heu, il se passe quoi si le fichier fait 4Go ?
    Un OutOfMemoryError... mais c'est tout à fait normal

    Mais il y a surtout trois points qui me chiffonne bien plus que cela :
    • La fermeture du flux n'est pas dans un bloc finally... en cas d'erreur lors de la lecture le fichier ne sera pas fermé...
    • available() ne renvoi pas la taille du fichier, mais une "estimation" du nombre de byte qui peuvent être lu sans provoquer de bloquage d'I/O. Avec de petit fichier cela peut très bien marcher... mais si le fichier est de taille conséquente on risque de tronquer la lecture ! De plus certain type d'InputStream peuvent très bien toujours renvoyer 0 !!!
    • De même, rien ne garantie qu'un seul appel à read() permettra de lire la totalité du fichier...


    Citation Envoyé par jibbi Voir le message
    On peut faire ca avec un ByteArrayInputStream
    Plutôt un ByteArrayOutputStream...


    Cela donnerait ceci, en utilisant une lecture par bloc de 8192 bytes :
    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
    	public byte[] getBytes(String filepath) throws IOException {
    	    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    	    FileInputStream in = new FileInputStream(filepath);
    	    try {
    	    	// On lit par bloc de 8192 bytes :
    	    	byte[] buf = new byte[8192];
    	    	int len;
     
    	    	while ( (len=in.read(buf)) >= 0) {
    	    		baos.write(buf, 0, len);
    	    	}
    	    } finally {
    	    	in.close();
    	    }
    	    return baos.toByteArray();
    	}
    Le ByteArrayOutputStream se redimensionne automatiquement lorsque c'est nécessaire (tout comme les StringBuffer/StringBuilder). Le gros problème de cette solution c'est que la méthode toByteArray() renvoi une copie du tableau généré, et que pendant un moment on se retrouve avec les données en double en mémoire, ce qui peut être pénalisant pour de gros fichier.

    Dans ce cas il faudrait plutôt se baser sur la méthode length() de File et gérer la lecture en boucle :
    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
    	public byte[] getBytes(String filepath) throws IOException {
    		File file = new File(filepath);
    		long length = file.length();
     
    		if (length<=0) {
    			throw new IOException("Taille de fichier incorrecte...");
    			/* Note : dans ce cas on pourrait envisager une lecture
    			 * via un ByteArrayOutputStream, car length() peut renvoyer 0
    			 * avec certains fichiers spéciaux du système d'exploitation
    			 */
    		}
     
    		if (length>Integer.MAX_VALUE) {
    			throw new IOException("Fichier trop grand...");
    			/* Note : cela permet d'éviter des erreurs à cause
    			 * du cast de long en int qui donnerait une valeur négatives
    			 */
    		}
     
    		// Création du buffer :
    		int toRead = (int) length;
    		byte[] buf = new byte[toRead];
     
    	    FileInputStream in = new FileInputStream(filepath);
    	    try {
    	    	int index = 0;
    	    	int read;
     
    	    	while (toRead>0) {
    	    		read = in.read(buf, index, toRead);
    	    		index += read;
    	    		toRead -= toRead;
    	    	}
    	    } finally {
    	    	in.close();
    	    }
    	    return buf;
    	}
    A noter qu'on pourrait également utiliser un ByteBuffer... voir directement un MappedByteBuffer pour de gros fichier (voir FileChannel.map()).


    a++

  8. #8
    Membre chevronné
    Profil pro
    Inscrit en
    Octobre 2007
    Messages
    442
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2007
    Messages : 442
    Par défaut
    Citation Envoyé par adiGuba Voir le message
    [*]La fermeture du flux n'est pas dans un bloc finally... en cas d'erreur lors de la lecture le fichier ne sera pas fermé...
    En temps normal je mets toujours le close() dans un finally mais là c'est vrai j'avais la flemme de le mettre pour l'exemple.

    Citation Envoyé par adiGuba Voir le message
    [*]available() ne renvoi pas la taille du fichier, mais une "estimation" du nombre de byte qui peuvent être lu sans provoquer de bloquage d'I/O. Avec de petit fichier cela peut très bien marcher... mais si le fichier est de taille conséquente on risque de tronquer la lecture ! De plus certain type d'InputStream peuvent très bien toujours renvoyer 0 !!![*]De même, rien ne garantie qu'un seul appel à read() permettra de lire la totalité du fichier...
    Je ne savais pas que available() retourne une estimation, c'est bon à savoir, merci !

    Sur des petits fichiers je n'ai jamais eut aucun problème, quant aux gros fichier je ne renvoie pas un tableau de byte[] mais je le traite par packets puisque tu vas l'avoir tout pareil ton OutOfMemoryError si tu charges un fichier de 4Go dans un byte[], non ?

  9. #9
    Expert éminent
    Avatar de adiGuba
    Homme Profil pro
    Développeur Java/Web
    Inscrit en
    Avril 2002
    Messages
    13 938
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Java/Web
    Secteur : Transports

    Informations forums :
    Inscription : Avril 2002
    Messages : 13 938
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par Duc Lebowski Voir le message
    En temps normal je mets toujours le close() dans un finally mais là c'est vrai j'avais la flemme de le mettre pour l'exemple.
    Oui mais j'aime bien le répéter car il me semble qu'il est un peu trop souvent oublié

    Citation Envoyé par Duc Lebowski Voir le message
    Sur des petits fichiers je n'ai jamais eut aucun problème, quant aux gros fichier je ne renvoie pas un tableau de byte[] mais je le traite par packets puisque tu vas l'avoir tout pareil ton OutOfMemoryError si tu charges un fichier de 4Go dans un byte[], non ?
    C'est bien le problème : la plupart du temps cela marche correctement !

    Mais cela ne dépend pas que de la taille du fichier, mais également de la JVM ou du système d'exploitation, voir même du type de matériel (lecteur de disquette) ou de l'emplacement du fichier (lecteur réseaux).

    Le jour où cela ne fonctionne plus le problème est difficile à trouver



    Pour le OutOfMemory c'est un autre problème par contre : il est clair que si on doit traiter de très gros fichier il faut éviter de les charger en entier en mémoire

    a++

  10. #10
    Membre chevronné
    Profil pro
    Inscrit en
    Octobre 2007
    Messages
    442
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2007
    Messages : 442
    Par défaut
    Merci pour ces précisions adiGuba. Effectivement je connais quelqu'un qui a eut un problème de lecture de fichier et il me disait que cela marchait sur certaines JVM et pas sur d'autres.

  11. #11
    Membre Expert Avatar de herve91
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    1 282
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2004
    Messages : 1 282
    Par défaut
    Citation Envoyé par adiGuba Voir le message
    Le gros problème de cette solution c'est que la méthode toByteArray() renvoi une copie du tableau généré, et que pendant un moment on se retrouve avec les données en double en mémoire, ce qui peut être pénalisant pour de gros fichier.
    Juste pour information, pour éviter cela, j'avais utilisé :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    ByteArrayOutputStream out = new ByteArrayOutputStream(size) {
      /**
       * overriden to prevent byte array allocation
       */
      public synchronized byte toByteArray()[] {
        return super.buf;
      }
    };

  12. #12
    Membre Expert
    Profil pro
    Fabrication GED
    Inscrit en
    Octobre 2005
    Messages
    1 405
    Détails du profil
    Informations personnelles :
    Âge : 46
    Localisation : France, Seine Maritime (Haute Normandie)

    Informations professionnelles :
    Activité : Fabrication GED

    Informations forums :
    Inscription : Octobre 2005
    Messages : 1 405
    Par défaut
    Citation Envoyé par adiGuba Voir le message
    ... voir directement un MappedByteBuffer pour de gros fichier (voir FileChannel.map()).
    Pour l'avoir déjà utilisé, je n'y ai pas trouvé d'avantages dans la manipulation de fichiers texte (encodage/decodage en mémoire quand même), ce que cherche à faire l'auteur du post.
    J'ai peut-être loupé un épisode sur le MappedByteBuffer, mais si qqn a une solution toute faite (dans le JDK) pour gérer une sorte de "MappedStringBuffer" couplé à un jeu de caractères particulier et paramétrable, qu'il se fasse connaître car je suis fortement intéressé.

  13. #13
    Expert éminent
    Avatar de adiGuba
    Homme Profil pro
    Développeur Java/Web
    Inscrit en
    Avril 2002
    Messages
    13 938
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Java/Web
    Secteur : Transports

    Informations forums :
    Inscription : Avril 2002
    Messages : 13 938
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par Duc Lebowski Voir le message
    Merci pour ces précisions adiGuba. Effectivement je connais quelqu'un qui a eut un problème de lecture de fichier et il me disait que cela marchait sur certaines JVM et pas sur d'autres.
    C'est justement le danger de ces méthodes dont le comportement n'est pas assuré ou variable

    Citation Envoyé par herve91 Voir le message
    Juste pour information, pour éviter cela, j'avais utilisé :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    ByteArrayOutputStream out = new ByteArrayOutputStream(size) {
      /**
       * overriden to prevent byte array allocation
       */
      public synchronized byte toByteArray()[] {
        return super.buf;
      }
    };
    C'est une solution... mais elle pose aussi un problème (sinon ce serait trop simple).
    Comme la plupart des classes qui gère un tableau redimensionnable, le tableau est généralement bien plus grand que la taille réellement utile. Ainsi à chaque modification du tableau si il est trop petit sa taille est doublé. Cela évites des redimensionnement trop fréquent qui peuvent plomber les perfs (il me semble que Firefox avait eu un bug similaire avec la lecture de son fichier historique).
    Par contre cela consomme logiquement plus de mémoire (à moins d'avoir beaucoup de chance pour tomber pile poil).

    A la rigueur cela pourrait être une solution si on utilise le constructeur de ByteArrayOutputStream en lui spécifiant une taille initiale et que l'on est sûr de ne pas la dépasser...

    Sinon il n'y a pas vraiment d'autre solution. Malheureusement les tableaux ne sont pas directement resizable en Java...

    Citation Envoyé par iohack Voir le message
    Pour l'avoir déjà utilisé, je n'y ai pas trouvé d'avantages dans la manipulation de fichiers texte (encodage/decodage en mémoire quand même), ce que cherche à faire l'auteur du post.
    J'ai peut-être loupé un épisode sur le MappedByteBuffer, mais si qqn a une solution toute faite (dans le JDK) pour gérer une sorte de "MappedStringBuffer" couplé à un jeu de caractères particulier et paramétrable, qu'il se fasse connaître car je suis fortement intéressé.
    Et en utilisant la méthode Charset.decode() ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    	MappedByteBuffer byteBuffer = channel.map(MapMode.READ_ONLY, 0, channel.size());
    	Charset charset = Charset.forName("iso-8859-1");
    	CharBuffer charBuffer = charset.decode(byteBuffer);

    a++

  14. #14
    Membre Expert
    Profil pro
    Fabrication GED
    Inscrit en
    Octobre 2005
    Messages
    1 405
    Détails du profil
    Informations personnelles :
    Âge : 46
    Localisation : France, Seine Maritime (Haute Normandie)

    Informations professionnelles :
    Activité : Fabrication GED

    Informations forums :
    Inscription : Octobre 2005
    Messages : 1 405
    Par défaut
    Citation Envoyé par adiGuba Voir le message
    CharBuffer charBuffer = charset.decode(byteBuffer);
    c'est bien là le problème, à ce moment précis, il n'y a plus de mapping disque mais un CharBuffer chargé en mémoire... Il faudrait un MappedCharBuffer qui n'existe pas (à priori pas encore, les charsets étant trop nombreux et trop spécifiques au système d'exploitation).
    Dis moi si je me trompe...
    Si le sujet vous intéresse, j'avais commencé à coder des choses dans cette voie : à savoir le mapping de fichier, ça, bufferisé, et le tout gérable dans une TextArea. Faire une recherche sur MapedBufferedTextArea. Je n'ai pas avancé, mais le principe y est décrit.

  15. #15
    Expert éminent
    Avatar de adiGuba
    Homme Profil pro
    Développeur Java/Web
    Inscrit en
    Avril 2002
    Messages
    13 938
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Java/Web
    Secteur : Transports

    Informations forums :
    Inscription : Avril 2002
    Messages : 13 938
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par iohack Voir le message
    c'est bien là le problème, à ce moment précis, il n'y a plus de mapping disque mais un CharBuffer chargé en mémoire...
    En effet c'est fort probable...

    Le problème vient surement du fait qu'un caractère peut être codé sur un nombre variable de byte selon l'encodage... ce qui rend impossible le mapping direct.

    a++

Discussions similaires

  1. Les manipulations de bits en Cobol
    Par Pralinor dans le forum Contribuez
    Réponses: 7
    Dernier message: 02/04/2009, 01h39
  2. Manipulations sur les bits
    Par ThE_LaSt dans le forum C
    Réponses: 23
    Dernier message: 27/03/2006, 15h22
  3. opérations sur les bits d'un byte
    Par petitours dans le forum C++Builder
    Réponses: 4
    Dernier message: 10/02/2004, 21h42
  4. Manipuler les fenêtre d'un shell en c
    Par Gential dans le forum C
    Réponses: 2
    Dernier message: 24/10/2003, 10h04
  5. [VB6]manipuler les semaines en VB ?
    Par kamadji dans le forum VB 6 et antérieur
    Réponses: 7
    Dernier message: 02/05/2003, 13h33

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