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 :

Channels et écriture dans un fichier


Sujet :

Entrée/Sortie Java

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    44
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2004
    Messages : 44
    Par défaut Channels et écriture dans un fichier
    Afin d'améliorer les performances de mon appli au moment de l'écriture dans un fichier, j'ai choisi d'utiliser le package java.nio.

    J'ai donc développé 4 méthodes de lectures et d'écritures utilisant plusieurs moyens différents afin d'observer les performances des unes et des autres.

    J'ai été très surpris d'observer les résultats suivants
    On y observe que :
    - la lecture avec les channels est performante, mais moins qu'avec les BufferedReaders
    - l'écriture avec les channels est le moyen le plus long des 4 (FileWriter, BufferedWriter, OutputStream et Channel)

    Voici mon code:
    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
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    package com.tests.channels;
     
    import java.io.BufferedOutputStream;
    import java.io.BufferedReader;
    import java.io.BufferedWriter;
    import java.io.File;
    import java.io.FileInputStream;
    import java.io.FileOutputStream;
    import java.io.FileReader;
    import java.io.FileWriter;
    import java.io.IOException;
    import java.io.OutputStream;
    import java.nio.ByteBuffer;
    import java.nio.CharBuffer;
    import java.nio.channels.Channels;
    import java.nio.channels.FileChannel;
    import java.nio.channels.WritableByteChannel;
    import java.nio.charset.Charset;
    import java.nio.charset.CharsetEncoder;
     
    public class Test
    {
        public static final String TEXT = "La bataille d'Héraclée est une bataille de l'Antiquité (280 av. J.-C.) qui vit s'affronter d'une part les troupes de la République romaine, commandées par le consul Publius Valerius Laevinus et d'autre part celles de la coalition grecque d'Épire, de Tarente, de Thurii, de Métaponte et d'Héraclée, sous le commandement du roi d'Épire, Pyrrhus Ier. Les Grecs, conduits par un de leurs généraux les plus talentueux, remportèrent la victoire.\nLa bataille d'Héraclée est une bataille de l'Antiquité (280 av. J.-C.) qui vit s'affronter d'une part les troupes de la République romaine, commandées par le consul Publius Valerius Laevinus et d'autre part celles de la coalition grecque d'Épire, de Tarente, de Thurii, de Métaponte et d'Héraclée, sous le commandement du roi d'Épire, Pyrrhus Ier. Les Grecs, conduits par un de leurs généraux les plus talentueux, remportèrent la victoire.\nLa bataille d'Héraclée est une bataille de l'Antiquité (280 av. J.-C.) qui vit s'affronter d'une part les troupes de la République romaine, commandées par le consul Publius Valerius Laevinus et d'autre part celles de la coalition grecque d'Épire, de Tarente, de Thurii, de Métaponte et d'Héraclée, sous le commandement du roi d'Épire, Pyrrhus Ier. Les Grecs, conduits par un de leurs généraux les plus talentueux, remportèrent la victoire.\nLa bataille d'Héraclée est une bataille de l'Antiquité (280 av. J.-C.) qui vit s'affronter d'une part les troupes de la République romaine, commandées par le consul Publius Valerius Laevinus et d'autre part celles de la coalition grecque d'Épire, de Tarente, de Thurii, de Métaponte et d'Héraclée, sous le commandement du roi d'Épire, Pyrrhus Ier. Les Grecs, conduits par un de leurs généraux les plus talentueux, remportèrent la victoire.\nLa bataille d'Héraclée est une bataille de l'Antiquité (280 av. J.-C.) qui vit s'affronter d'une part les troupes de la République romaine, commandées par le consul Publius Valerius Laevinus et d'autre part celles de la coalition grecque d'Épire, de Tarente, de Thurii, de Métaponte et d'Héraclée, sous le commandement du roi d'Épire, Pyrrhus Ier. Les Grecs, conduits par un de leurs généraux les plus talentueux, remportèrent la victoire.\nLa bataille d'Héraclée est une bataille de l'Antiquité (280 av. J.-C.) qui vit s'affronter d'une part les troupes de la République romaine, commandées par le consul Publius Valerius Laevinus et d'autre part celles de la coalition grecque d'Épire, de Tarente, de Thurii, de Métaponte et d'Héraclée, sous le commandement du roi d'Épire, Pyrrhus Ier. Les Grecs, conduits par un de leurs généraux les plus talentueux, remportèrent la victoire.\nLa bataille d'Héraclée est une bataille de l'Antiquité (280 av. J.-C.) qui vit s'affronter d'une part les troupes de la République romaine, commandées par le consul Publius Valerius Laevinus et d'autre part celles de la coalition grecque d'Épire, de Tarente, de Thurii, de Métaponte et d'Héraclée, sous le commandement du roi d'Épire, Pyrrhus Ier. Les Grecs, conduits par un de leurs généraux les plus talentueux, remportèrent la victoire.\nLa bataille d'Héraclée est une bataille de l'Antiquité (280 av. J.-C.) qui vit s'affronter d'une part les troupes de la République romaine, commandées par le consul Publius Valerius Laevinus et d'autre part celles de la coalition grecque d'Épire, de Tarente, de Thurii, de Métaponte et d'Héraclée, sous le commandement du roi d'Épire, Pyrrhus Ier. Les Grecs, conduits par un de leurs généraux les plus talentueux, remportèrent la victoire.\n";
     
        public static void main(String[] args) throws IOException
        {
            Charset charset = Charset.forName("ISO-8859-1");
            // Charset charset = Charset.forName("UTF-8");
            // Charset charset = Charset.forName("US-ASCII");
     
            File fileChannels = new File("C:/temp/testChannels.txt");
            File fileIO = new File("C:/temp/testFileRW.txt");
            File fileOS = new File("C:/temp/testOutputStream.txt");
            File fileBW = new File("C:/temp/testBufferedRW.txt");
            /*
             * Writing tests
             */
            Test.writeWithFileWriter(fileIO, Test.TEXT);
            Test.writeWithBufferedWriter(fileBW, Test.TEXT);
            Test.writeWithOutputStream(fileOS, Test.TEXT);
            Test.writeWithChannel(charset, fileChannels, Test.TEXT);
            /*
             * Reading tests
             */
            Test.readWithFileReader(fileIO);
            Test.readWithBufferedReader(fileIO);
            Test.readWithInputStream(fileIO);
            Test.readWithChannel(charset, fileIO);
        }
     
        /**
         * @param args
         * @throws IOException
         */
        public static void writeWithChannel(Charset charset, File file, String text) throws IOException
        {
            CharsetEncoder encoder = charset.newEncoder();
            file.createNewFile();
            OutputStream fos = new FileOutputStream(file);
            WritableByteChannel channel = Channels.newChannel(fos);
            ByteBuffer bb = encoder.encode(CharBuffer.wrap(text));
            channel.write(bb);
            channel.close();
            fos.close();
        }
     
        public static void readWithChannel(Charset charset, File aFile) throws IOException
        {
            System.out.println("Test.readWithChannel()");
            FileInputStream inFile = new FileInputStream(aFile);
            FileChannel inChannel = inFile.getChannel();
            ByteBuffer buf = ByteBuffer.allocate((int) aFile.length());
            CharBuffer outBuff = CharBuffer.allocate((int) aFile.length());
            inChannel.read(buf);
            buf.flip();
            outBuff = charset.decode((ByteBuffer) buf);
            System.out.println(outBuff);
            inFile.close();
        }
     
        /***************************************************************************
         * 
         **************************************************************************/
        public static void writeWithFileWriter(File file, String text) throws IOException
        {
            file.createNewFile();
            FileWriter writer = new FileWriter(file);
            writer.write(text);
            writer.close();
        }
     
        public static void readWithFileReader(File file) throws IOException
        {
            System.out.println("Test.readWithFileReader()");
            FileReader reader = new FileReader(file);
            int i = 0;
            while ((i = reader.read()) != -1)
            {
                System.out.print((char) i);
            }
            reader.close();
     
        }
     
        /***************************************************************************
         * 
         **************************************************************************/
        public static void readWithBufferedReader(File file) throws IOException
        {
            System.out.println("Test.readWithBufferedReader()");
            BufferedReader reader = new BufferedReader(new FileReader(file));
            String st;
            while ((st = reader.readLine()) != null)
            {
                System.out.println(st);
            }
            reader.close();
        }
     
        public static void writeWithBufferedWriter(File file, String text) throws IOException
        {
          BufferedWriter writer = new BufferedWriter(new FileWriter(file));
          writer.write(text);
          writer.close();
        }
     
        /***************************************************************************
         * 
         **************************************************************************/
        public static void readWithInputStream(File file) throws IOException
        {
            System.out.println("Test.readWithInputStream()");
            FileInputStream reader = new FileInputStream(file);
            int i = 0;
            while ((i = reader.read()) != -1)
            {
                System.out.print((char) i);
            }
            reader.close();
        }
     
        private static void writeWithOutputStream(File file, String text) throws IOException
        {
            file.createNewFile();
            BufferedOutputStream writer = new BufferedOutputStream(new FileOutputStream(file));
            writer.write(text.getBytes());
            writer.close();
        }
    }
    Je serais très intéressé par votre avis sur l'utilisation que je fais des différents moyen d'écriture, et sur la raison pour laquelle Les FileReader et FileWriter semblent plus rapides (ce qui me ferait poser de sérieux doutes sur l'intérêt de java.nio alors).

  2. #2
    Membre émérite
    Profil pro
    Inscrit en
    Février 2007
    Messages
    572
    Détails du profil
    Informations personnelles :
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations forums :
    Inscription : Février 2007
    Messages : 572
    Par défaut
    A mon avis, tu fais quelques erreurs dans tes tests :
    - dans writeWithChannel. C'est la seule methode a refaire un encoding de la chaine.
    - le test ne represente pas le cas reel. J'imagine que tes problemes de performance n'apparaissent pas sur des fichiers textes qui font quelques dizaines de chaine de caracteres.

    Je ne sais pas comment tu fais les mesures de temps, mais si c'est sur un seul appel, ca n'est pas vraiment fiable. Il faut plutot lancer une centaine de fois les methodes pour avoir des statisques plus corrects.

    Attention aussi, la mesure peut être faussée par la transformation de la chaine en tableau de bytes. C'est peut être une operation assez longue, qui masque du coup les differences entre les differents modes d'ecriture.

    Enfin, en dehors des performances, java.nio permet un controle plus fin de l'ecriture, de la lecture, et de la mise en memoire des données.

    I hope this helps

  3. #3
    Membre averti
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    44
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2004
    Messages : 44
    Par défaut
    WriteChannel est la seule méthode a faire un encoding parce que visiblement c'est plus ou moins pris en compte dans les autres types d'écriture.
    J'avais posté un topic ici par rapport aux channels. Je m'étais aperçu que sans encodage, j'avais des problèmes de lecture du fichier.
    Cela dit, j'ai effectué les tests sans encodage, et j'obtiens des résultats très légèrement plus faibles.

    J'ai réalisé les mêmes tests en mettant une boucle de 1000 itérations autour de chaque écriture et lecture. Les résultats sont du même ordre.
    Mais peut-être cela n'est-il de tout façon pas pertinent... Peut-être devrais-je tester aussi l'écriture à la fin d'un fichier non vide.

    Attention aussi, la mesure peut être faussée par la transformation de la chaine en tableau de bytes. C'est peut être une operation assez longue, qui masque du coup les differences entre les differents modes d'ecriture.
    Puis-je faire autrement, en passant par les Channels, qu'utiliser un byteBuffer ?

    Je m'étonne surtout que les FileReader et FileWriter soient plus performants.

    PS: mes tests de performance sont réalisés avec le plugin TPTP d'eclipse

  4. #4
    Membre émérite
    Profil pro
    Inscrit en
    Février 2007
    Messages
    572
    Détails du profil
    Informations personnelles :
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations forums :
    Inscription : Février 2007
    Messages : 572
    Par défaut
    WriteChannel est la seule méthode a faire un encoding parce que visiblement c'est plus ou moins pris en compte dans les autres types d'écriture.
    Dans ta methode writeWithOutputStream(), tu utilises String.getBytes(), pour faire l'encoding.
    Tu pourrais faire la meme chose pour writeWithChannel(), avec une ligne du type
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    ByteBuffer buffer = ByteBuffer.wrap(text.getBytes());
    Ce que je voulais dire par " la mesure peut être faussée par la transformation de la chaine en tableau de bytes", c'est que String.getBytes() peut representer dans tes methodes plus de 50% du temps. Je suis d'accord pour dire que tu ne peux pas t'en passer, mais ca peut expliquer pourquoi FileWriter prend moins de temps : cette classe, qui peut disposer d'un acces priviligié aux attributs de String, peut optimiser la conversion.

  5. #5
    Membre averti
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    44
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2004
    Messages : 44
    Par défaut
    Ce que je voulais dire par " la mesure peut être faussée par la transformation de la chaine en tableau de bytes", c'est que String.getBytes() peut representer dans tes methodes plus de 50% du temps. Je suis d'accord pour dire que tu ne peux pas t'en passer, mais ca peut expliquer pourquoi FileWriter prend moins de temps : cette classe, qui peut disposer d'un acces priviligié aux attributs de String, peut optimiser la conversion.
    Je saisis l'idée.
    Il n'en reste pas moins que si les FileWriter et FileReader sont plus performants (résultat curieux quand on lit cet article sur les Channels), je ne vois pas l'intérêt du package java.nio.
    Je vais investiguer pour voir si les conditions d'utilisation de l'un et de l'autre sont similaires.

  6. #6
    Membre averti
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    44
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2004
    Messages : 44
    Par défaut
    Verdict: ce qui est très long dans ma méthode d'écriture avec les channels, c'est la conversion d'une String en un tableau de char[].
    En effet, en passant comme paramètre un char[] au lieu d'une String, je passe de 36% à 14,23 ms à 1,70 ms

    Les channels ont donc des performances très supérieures aux autres modes d'écriture et de lecture.

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

Discussions similaires

  1. Réponses: 3
    Dernier message: 18/08/2005, 11h57
  2. [PERL] Problème lecture/écriture dans un fichier
    Par LE NEINDRE dans le forum Langage
    Réponses: 4
    Dernier message: 17/08/2005, 13h15
  3. Problème d'écriture dans un fichier xml
    Par vanoou dans le forum C++Builder
    Réponses: 1
    Dernier message: 13/07/2005, 02h28
  4. Passer à la ligne lors de l'écriture dans un fichier
    Par hams dans le forum Assembleur
    Réponses: 4
    Dernier message: 17/04/2005, 19h25
  5. [JUnit] Junit écriture dans un fichier
    Par mikael35 dans le forum Tests et Performance
    Réponses: 1
    Dernier message: 10/08/2004, 13h11

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