performance d'un - Comment lire un gros fichier texte ligne par ligne en utilisant Java?





récupérer données (17)


Le moyen clair d'y parvenir,

Par exemple:

Si vous avez dataFile.txt sur votre répertoire actuel

import java.io.*;
import java.util.Scanner;
import java.io.FileNotFoundException;

public class readByLine
{
    public readByLine() throws FileNotFoundException
    {
        Scanner linReader = new Scanner(new File("dataFile.txt"));

        while (linReader.hasNext())
        {
            String line = linReader.nextLine();
            System.out.println(line);
        }
        linReader.close();

    }

    public static void main(String args[])  throws FileNotFoundException
    {
        new readByLine();
    }
}

La sortie comme ci-dessous,

J'ai besoin de lire un gros fichier texte d'environ 5-6 Go ligne par ligne en utilisant Java.

Comment puis-je le faire rapidement?




FileReader ne vous laissera pas spécifier l'encodage, utilisez plutôt InputStreamReader si vous avez besoin de le spécifier:

try {
    BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(filePath), "Cp1252"));         

    String line;
    while ((line = br.readLine()) != null) {
        // process the line.
    }
    br.close();

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

Si vous avez importé ce fichier à partir de Windows, il est possible qu'il ait un codage ANSI (Cp1252), vous devez donc spécifier l'encodage.




Vous pouvez utiliser ce code:

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;

public class ReadTextFile {

    public static void main(String[] args) throws IOException {

        try {

            File f = new File("src/com/data.txt");

            BufferedReader b = new BufferedReader(new FileReader(f));

            String readLine = "";

            System.out.println("Reading file using Buffered Reader");

            while ((readLine = b.readLine()) != null) {
                System.out.println(readLine);
            }

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

    }

}



Regardez ce blog:

La taille de la mémoire tampon peut être spécifiée ou la taille par défaut peut être utilisée. La valeur par défaut est suffisamment grande pour la plupart des cas.

// Open the file
FileInputStream fstream = new FileInputStream("textfile.txt");
BufferedReader br = new BufferedReader(new InputStreamReader(fstream));

String strLine;

//Read File Line By Line
while ((strLine = br.readLine()) != null)   {
  // Print the content on the console
  System.out.println (strLine);
}

//Close the input stream
br.close();



Voici un exemple avec la gestion complète des erreurs et la spécification de charset de support pour pré-Java 7. Avec Java 7, vous pouvez utiliser la syntaxe try-with-resources, ce qui rend le code plus propre.

Si vous voulez juste le jeu de caractères par défaut, vous pouvez ignorer InputStream et utiliser FileReader.

InputStream ins = null; // raw byte-stream
Reader r = null; // cooked reader
BufferedReader br = null; // buffered for readLine()
try {
    String s;
    ins = new FileInputStream("textfile.txt");
    r = new InputStreamReader(ins, "UTF-8"); // leave charset out for default
    br = new BufferedReader(r);
    while ((s = br.readLine()) != null) {
        System.out.println(s);
    }
}
catch (Exception e)
{
    System.err.println(e.getMessage()); // handle exception
}
finally {
    if (br != null) { try { br.close(); } catch(Throwable t) { /* ensure close happens */ } }
    if (r != null) { try { r.close(); } catch(Throwable t) { /* ensure close happens */ } }
    if (ins != null) { try { ins.close(); } catch(Throwable t) { /* ensure close happens */ } }
}

Voici la version Groovy, avec gestion complète des erreurs:

File f = new File("textfile.txt");
f.withReader("UTF-8") { br ->
    br.eachLine { line ->
        println line;
    }
}



J'ai documenté et testé 10 façons différentes de lire un fichier en Java , puis les ai couru les uns contre les autres en les faisant lire dans des fichiers de test de 1KB à 1GB. Voici les 3 méthodes de lecture de fichier les plus rapides pour lire un fichier de test de 1 Go.

Notez que lors de l'exécution des tests de performance, je n'ai rien affiché sur la console car cela ralentirait vraiment le test. Je voulais juste tester la vitesse de lecture brute.

1) java.nio.file.Files.readAllBytes ()

Testé en Java 7, 8, 9. C'était globalement la méthode la plus rapide. La lecture d'un fichier de 1 Go était systématiquement inférieure à 1 seconde.

import java.io..File;
import java.io.IOException;
import java.nio.file.Files;

public class ReadFile_Files_ReadAllBytes {
  public static void main(String [] pArgs) throws IOException {
    String fileName = "c:\\temp\\sample-1GB.txt";
    File file = new File(fileName);

    byte [] fileBytes = Files.readAllBytes(file.toPath());
    char singleChar;
    for(byte b : fileBytes) {
      singleChar = (char) b;
      System.out.print(singleChar);
    }
  }
}

2) java.nio.file.Files.lines ()

Cela a été testé avec succès dans Java 8 et 9 mais cela ne fonctionnera pas dans Java 7 en raison du manque de support pour les expressions lambda. Il a fallu environ 3,5 secondes pour lire dans un fichier de 1 Go ce qui le place en deuxième position pour la lecture de fichiers plus volumineux.

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.util.stream.Stream;

public class ReadFile_Files_Lines {
  public static void main(String[] pArgs) throws IOException {
    String fileName = "c:\\temp\\sample-1GB.txt";
    File file = new File(fileName);

    try (Stream linesStream = Files.lines(file.toPath())) {
      linesStream.forEach(line -> {
        System.out.println(line);
      });
    }
  }
}

3) BufferedReader

Testé pour fonctionner dans Java 7, 8, 9. Cela a pris environ 4,5 secondes pour lire dans un fichier de test de 1 Go.

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;

public class ReadFile_BufferedReader_ReadLine {
  public static void main(String [] args) throws IOException {
    String fileName = "c:\\temp\\sample-1GB.txt";
    FileReader fileReader = new FileReader(fileName);

    try (BufferedReader bufferedReader = new BufferedReader(fileReader)) {
      String line;
      while((line = bufferedReader.readLine()) != null) {
        System.out.println(line);
      }
    }
  }

Vous pouvez trouver le classement complet pour les 10 méthodes de lecture de fichiers here .




BufferedReader br;
FileInputStream fin;
try {
    fin = new FileInputStream(fileName);
    br = new BufferedReader(new InputStreamReader(fin));

    /*Path pathToFile = Paths.get(fileName);
    br = Files.newBufferedReader(pathToFile,StandardCharsets.US_ASCII);*/

    String line = br.readLine();
    while (line != null) {
        String[] attributes = line.split(",");
        Movie movie = createMovie(attributes);
        movies.add(movie);
        line = br.readLine();
    }
    fin.close();
    br.close();
} catch (FileNotFoundException e) {
    System.out.println("Your Message");
} catch (IOException e) {
    System.out.println("Your Message");
}

Ça marche pour moi. J'espère que cela vous aidera aussi.




Un modèle commun est d'utiliser

try (BufferedReader br = new BufferedReader(new FileReader(file))) {
    String line;
    while ((line = br.readLine()) != null) {
       // process the line.
    }
}

Vous pouvez lire les données plus rapidement si vous supposez qu'il n'y a pas d'encodage de caractères. par exemple ASCII-7 mais cela ne fera pas beaucoup de différence. Il est fort probable que ce que vous ferez avec les données prendra beaucoup plus de temps.

EDIT: Un modèle moins commun à utiliser qui évite l'étendue de la fuite de line .

try(BufferedReader br = new BufferedReader(new FileReader(file))) {
    for(String line; (line = br.readLine()) != null; ) {
        // process the line.
    }
    // line is not visible here.
}

UPDATE: En Java 8, vous pouvez faire

try (Stream<String> stream = Files.lines(Paths.get(fileName))) {
        stream.forEach(System.out::println);
}

Remarque: vous devez placer le flux dans un bloc try-with-resource pour vous assurer que la méthode #close est appelée, sinon le handle de fichier sous-jacent n'est jamais fermé jusqu'à ce que GC le fasse beaucoup plus tard.




Je fais d'habitude la routine de lecture simple:

void readResource(InputStream source) throws IOException {
    BufferedReader stream = null;
    try {
        stream = new BufferedReader(new InputStreamReader(source));
        while (true) {
            String line = stream.readLine();
            if(line == null) {
                break;
            }
            //process line
            System.out.println(line)
        }
    } finally {
        closeQuiet(stream);
    }
}

static void closeQuiet(Closeable closeable) {
    if (closeable != null) {
        try {
            closeable.close();
        } catch (IOException ignore) {
        }
    }
}



Java-9:

try (Stream<String> stream = Files.lines(Paths.get(fileName))) {
        stream.forEach(System.out::println);
}



En Java 8, vous pouvez faire:

try (Stream<String> lines = Files.lines (file, StandardCharsets.UTF_8))
{
    for (String line : (Iterable<String>) lines::iterator)
    {
        ;
    }
}

Quelques notes: Le flux retourné par Files.lines (contrairement à la plupart des flux) doit être fermé. Pour les raisons mentionnées ici, j'évite d'utiliser forEach() . Le code étrange (Iterable<String>) lines::iterator projette un Stream vers un Iterable.




Ce que vous pouvez faire est de scanner le texte entier en utilisant Scanner et de parcourir le texte ligne par ligne. Bien sûr, vous devriez importer ce qui suit:

import java.io.File;
import java.io.FileNotFoundException;
import java.util.Scanner;
public static void readText throws FileNotFoundException {
    Scanner scan = new Scanner(new File("samplefilename.txt"));
    while(scan.hasNextLine()){
        String line = scan.nextLine();
        //Here you can manipulate the string the way you want
    }
}

Le scanner scanne tout le texte. La boucle while est utilisée pour traverser le texte entier.

La fonction .hasNextLine() est un booléen qui retourne true s'il y a encore plus de lignes dans le texte. La fonction .nextLine() vous donne une ligne entière en tant que chaîne que vous pouvez ensuite utiliser comme vous le souhaitez. Essayez System.out.println(line) pour imprimer le texte.

Side Note: .txt est le texte du type de fichier.




Vous pouvez utiliser la classe Scanner

Scanner sc=new Scanner(file);
sc.nextLine();



En Java 8, il existe également une alternative à l'utilisation de Files.lines() . Si votre source d'entrée n'est pas un fichier mais quelque chose de plus abstrait comme un Reader ou un InputStream , vous pouvez streamer les lignes via la méthode s BufferedReader lines() BufferedReader .

Par exemple:

try( BufferedReader reader = new BufferedReader( ... ) ) {
  reader.lines().foreach( line -> processLine( line ) );
}

appellera processLine() pour chaque ligne d'entrée lue par BufferedReader .




Vous pouvez utiliser des flux pour le faire plus précisément:

Files.lines(Paths.get("input.txt")).forEach(s -> stringBuffer.append(s);



Une fois java-8 sorti (mars 2014), vous pourrez utiliser des flux:

try (Stream<String> lines = Files.lines(Paths.get(filename), Charset.defaultCharset())) {
  lines.forEachOrdered(line -> process(line));
}

Imprimer toutes les lignes du fichier:

try (Stream<String> lines = Files.lines(file, Charset.defaultCharset())) {
  lines.forEachOrdered(System.out::println);
}



Utilisez Integer.parseInt () et insérez-le dans un bloc try...catch pour gérer les erreurs au cas où un caractère non numérique est entré, par exemple,

private void ConvertToInt(){
    String string = txtString.getText();
    try{
        int integerValue=Integer.parseInt(string);
        System.out.println(integerValue);
    }
    catch(Exception e){
       JOptionPane.showMessageDialog(
         "Error converting string to integer\n" + e.toString,
         "Error",
         JOptionPane.ERROR_MESSAGE);
    }
 }




java performance file-io io garbage-collection