Comment lire un grand fichier texte ligne par ligne en utilisant Java?

j'ai besoin de lire un grand fichier texte d'environ 5-6 GO ligne par ligne en utilisant Java.

Comment puis-je faire cela rapidement?

704
demandé sur Peter Lawrey 2011-05-03 14:53:24

20 réponses

un schéma 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 de codage de caractères. par exemple ASCII-7 mais cela ne fera pas beaucoup de différence. Il est très probable que ce que vous faites avec les données prendra beaucoup plus de temps.

EDIT: un modèle moins commun à utiliser qui évite la portée de line fuite.

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

mise à jour: 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 "essayer avec les ressources" pour vous assurer que la méthode #close est activée, sinon le gestionnaire de fichier sous-jacent n'est jamais fermé jusqu'à ce que le GC le fasse beaucoup plus tard.

886
répondu Peter Lawrey 2017-11-02 16:51:20

Regardez ce blog:

la taille du tampon peut être spécifiée, ou la taille par défaut peut être utilisé. Le la taille par défaut est suffisante pour la plupart but.

// 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();
123
répondu Naveed 2013-08-02 14:11:13

une fois est sorti (mars 2014) vous pourrez utiliser les flux:

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

impression de toutes les lignes du fichier:

try (Stream<String> lines = Files.lines(file, Charset.defaultCharset())) {
  lines.forEachOrdered(System.out::println);
}
81
répondu msayag 2016-01-03 07:42:30

voici un exemple de spécification de charset 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 simplement le jeu de caractères par défaut, vous pouvez sauter L'entrée 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 le traitement complet des erreurs:

File f = new File("textfile.txt");
f.withReader("UTF-8") { br ->
    br.eachLine { line ->
        println line;
    }
}
35
répondu DarkStar 2018-04-15 13:19:39

Dans 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é ici j'évite d'utiliser forEach() . L'étrange code (Iterable<String>) lines::iterator envoie un flux à un itérable.

21
répondu Aleksandr Dubinsky 2017-05-23 12:10:44

ce que vous pouvez faire est de scanner le texte entier à L'aide D'un Scanner et de passer à travers le texte ligne par ligne. Bien sûr, vous devez 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 essentiellement tout le texte. La boucle while est utilisée pour parcourir tout le texte.

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 comme une corde que vous pouvez alors utilisez la façon que vous voulez. Essayez System.out.println(line) pour imprimer le texte.

Note De Côté: .txt est le type de fichier texte.

19
répondu iskandarchacra 2016-04-14 12:00:59

FileReader ne vous laissera pas spécifier l'encodage, utilisez InputStreamReader à la place 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 de Windows, il peut avoir un encodage ANSI (Cp1252), vous devez donc spécifier l'encodage.

17
répondu live-love 2017-07-20 04:04:14

En Java 7:

String folderPath = "C:/folderOfMyFile";
Path path = Paths.get(folderPath, "myFileName.csv"); //or any text file eg.: txt, bat, etc
Charset charset = Charset.forName("UTF-8");

try (BufferedReader reader = Files.newBufferedReader(path , charset)) {
  while ((line = reader.readLine()) != null ) {
    //separate all csv fields into string array
    String[] lineVariables = line.split(","); 
  }
} catch (IOException e) {
    System.err.println(e);
}
15
répondu Diego Duarte 2014-10-01 14:51:57

vous pouvez utiliser la classe de Scanner

Scanner sc=new Scanner(file);
sc.nextLine();
9
répondu Abhilash 2011-05-03 11:00:49

pour fichier de lecture avec java 8

  package com.java.java8;

    import java.nio.file.Files;
    import java.nio.file.Paths;
    import java.util.stream.Stream;

    /**
     * The Class ReadLargeFile.
     *
     * @author Ankit Sood Apr 20, 2017
     */
    public class ReadLargeFile {

        /**
         * The main method.
         *
         * @param args
         *            the arguments
         */
        public static void main(String[] args) {
        try {
            Stream<String> stream = Files.lines(Paths.get("C:\Users\System\Desktop\demoData.txt"));
            stream.forEach(System.out::println);
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        }
    }
9
répondu Ankit Sood 2017-04-20 09:45:48

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

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

1) Java.nio.fichier.Fichier.readAllBytes ()

testé en Java 7, 8, 9. C'était la méthode la plus rapide dans l'ensemble. La lecture d'un fichier de 1 Go a toujours été d'un peu moins d'une 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.fichier.Fichier.lines ()

cela a été testé avec succès en Java 8 et 9 mais cela ne fonctionnera pas en Java 7 en raison du manque de support pour les expressions lambda. Il a fallu environ 3,5 secondes pour lire dans un fichier 1 Go qui le plaçait à la deuxième place aussi loin que la lecture des 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 en Java 7, 8, 9. Cela a pris environ 4,5 secondes pour lire dans un fichier 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 l'ensemble des 10 méthodes de lecture de fichier ici .

9
répondu gomisha 2018-04-08 00:10:00

en Java 8, Il y a aussi une alternative à l'utilisation 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 BufferedReader s lines() .

par exemple:

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

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

8
répondu Rüdiger Herrmann 2017-05-23 12:26:33

vous devez utiliser la méthode readLine() dans class BufferedReader . Créer un nouvel objet de cette classe et de faire fonctionner cette méthode sur lui et l'enregistrer sur une chaîne.

BufferReader Javadoc

7
répondu Master C 2017-05-07 07:44:43

Java-9:

try (Stream<String> stream = Files.lines(Paths.get(fileName))) {
        stream.forEach(System.out::println);
}
6
répondu Abdennour TOUMI 2016-08-26 08:26:15

La claire-voie pour atteindre cet objectif,

par exemple:

si vous avez dataFile.txt dans votre répertoire courant

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, enter image description here

5
répondu Rajamohan S 2016-09-08 01:42:48
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 me va. Espérons qu'Il vous aidera aussi.

3
répondu Dipendra Ghatal 2017-09-17 10:32:02

je fais habituellement 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) {
        }
    }
}
2
répondu Binkan Salaryman 2015-05-22 08:08:41

vous pouvez également utiliser apache commons io :

File file = new File("/home/user/file.txt");
try {
    List<String> lines = FileUtils.readLines(file);
} catch (IOException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
}
0
répondu To Kra 2015-04-22 08:51:01

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();
        }

    }

}
0
répondu Usman Yaqoob 2017-10-26 19:42:54

vous pouvez utiliser les flux pour le faire plus précisément:

Files.lines(Paths.get("input.txt")).forEach(s -> stringBuffer.append(s);
-2
répondu spidy 2017-09-28 08:15:47