web-dev-qa-db-fra.com

Java - lecture à partir d'un fichier. Flux d'entrée vs lecteur

Dans chaque Java implémentation que je vois de la lecture d'un fichier, je vois presque toujours un lecteur de fichier utilisé pour lire ligne par ligne. Ma pensée serait que ce serait terriblement inefficace car il nécessite un système appel par ligne.

Ce que j'avais fait à la place, c'était d'utiliser un flux d'entrée et de saisir les octets directement. Dans mes expériences, c'est beaucoup plus rapide. Mon test était un fichier de 1 Mo.

    //Stream method
    try {
        Long startTime = new Date().getTime();

        InputStream is = new FileInputStream("test");
        byte[] b = new byte[is.available()];
        is.read(b);
        String text = new String(b);
        //System.out.println(text);

        Long endTime = new Date().getTime();
        System.out.println("Text length: " + text.length() + ", Total time: " + (endTime - startTime));

    }
    catch (Exception e) {
        e.printStackTrace();
    }

    //Reader method
    try {
        Long startTime = new Date().getTime();

        BufferedReader br = new BufferedReader(new FileReader("test"));
        String line = null;
        StringBuilder sb = new StringBuilder();
        while ((line = br.readLine()) != null) {
            sb.append(line);
            sb.append("\n");
        }
        String text = sb.toString();

        Long endTime = new Date().getTime();
        System.out.println("Text length: " + text.length() + ", Total time: " + (endTime - startTime));

    }
    catch (Exception e) {
        e.printStackTrace();
    }

Cela donne un résultat de:

Text length: 1054631, Total time: 9
Text length: 1034099, Total time: 22

Alors, pourquoi les gens utilisent-ils des lecteurs plutôt que des flux?

Si j'ai une méthode qui prend un fichier texte et retourne une chaîne qui contient tout le texte, est-il nécessairement préférable de le faire en utilisant un flux?

14
Jeremy

Vous comparez des pommes à des bananes. La lecture d'une ligne à la fois sera moins efficace, même avec un tampon de lecture, que la capture de données le plus rapidement possible. Notez que l'utilisation de disponible est déconseillée, car elle n'est pas exacte dans toutes les situations. Je l'ai découvert moi-même lorsque j'ai commencé à utiliser des flux de chiffrement.

9
ControlAltDel

Essayez d'augmenter la taille du tampon BufferedReader. Par exemple:

BufferedReader br = new BufferedReader(new FileReader("test"),2000000);

Si vous choisissez la bonne taille de tampon, vous serez plus rapide.

Ensuite, dans votre exemple avec Reader, vous passez du temps à remplir le StringBuilder. Vous devez lire le fichier ligne par ligne si vous avez besoin de traiter des lignes. Mais si vous avez seulement besoin de lire un texte dans une chaîne, lisez un plus gros morceau de texte avec public int read(char[] cbuf) et écrivez les morceaux dans un StringWriter initialisé avec une taille appropriée.

Choisissez d'utiliser InputStream ou Reader ne dépend pas des performances. En général, vous utilisez Reader lorsque vous lisez des données texte, car avec le lecteur, vous pouvez gérer plus facilement le jeu de caractères.

Un autre point, votre code ici

byte[] b = new byte[is.available()];
is.read(b);
String text = new String(b);

ce n'est pas correct. Le documentation indique

Notez que bien que certaines implémentations de InputStream renvoient le nombre total d'octets dans le flux, beaucoup ne le feront pas. Il n'est jamais correct d'utiliser la valeur de retour de cette méthode pour allouer un tampon destiné à contenir toutes les données de ce flux.

alors faites attention, vous devez le réparer.

3
dash1e

FileReader est généralement utilisé en conjonction avec un BufferedReader car il est souvent judicieux de lire un fichier ligne par ligne, spécialement si le fichier a une structure d'enregistrement bien définie où chaque enregistrement correspond à une ligne .

De plus, FileReader peut simplifier une partie du travail de gestion des encodages et des conversions de caractères, comme indiqué dans javadocs :

Cours pratique pour lire des fichiers de caractères. Les constructeurs de cette classe supposent que l'encodage des caractères par défaut et la taille du tampon d'octets par défaut sont appropriés ... FileReader est destiné à la lecture de flux de caractères.

3
Óscar López