Hoe kan ik een groot tekstbestand regel voor regel lezen met Java?

Ik moet een groot tekstbestand van ongeveer 5-6 GB regel voor regel lezen met Java.

Hoe kan ik dit snel doen?


Antwoord 1, autoriteit 100%

Een veelvoorkomend patroon is om te gebruiken

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

U kunt de gegevens sneller lezen als u ervan uitgaat dat er geen tekencodering is. bijv. ASCII-7, maar het zal niet veel verschil maken. Het is zeer waarschijnlijk dat wat u met de gegevens doet veel langer zal duren.

EDIT: een minder gebruikelijk patroon om te voorkomen dat de reikwijdte van linelekt.

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

UPDATE: in Java 8 kunt u dat doen

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

OPMERKING: je moet de stream in een try-with- resource-blok om ervoor te zorgen dat de #close-methode erop wordt aangeroepen, anders wordt de onderliggende bestandshandle nooit gesloten totdat GC dit veel later doet.


Antwoord 2, autoriteit 15%

Bekijk deze blog:

De buffergrootte kan worden opgegeven, of
de standaardgrootte kan worden gebruikt. De
standaard is groot genoeg voor de meeste
doeleinden.

// 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
fstream.close();

Antwoord 3, autoriteit 10%

Zodra Java 8 uit is (maart 2014), kun je streams gebruiken:

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

Alle regels in het bestand afdrukken:

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

Antwoord 4, autoriteit 3%

Hier is een voorbeeld met volledige foutafhandeling en ondersteunende karaktersetspecificatie voor pre-Java 7. Met Java 7 kunt u de syntaxis proberen-met-resources gebruiken, waardoor de code schoner wordt.

Als u alleen de standaardtekenset wilt, kunt u de InputStream overslaan en FileReader gebruiken.

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 */ } }
}

Hier is de Groovy-versie, met volledige foutafhandeling:

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

Antwoord 5, autoriteit 2%

Ik heb 10 verschillende manieren gedocumenteerd en getest om een ​​bestand in Java te lezenen heb ze vervolgens tegen elkaar uitgevoerd door waardoor ze testbestanden van 1KB tot 1GB inlezen. Dit zijn de 3 snelste bestandsleesmethoden voor het lezen van een testbestand van 1 GB.

Houd er rekening mee dat ik bij het uitvoeren van de prestatietests niets naar de console uitvoerde, omdat dat de test echt zou vertragen. Ik wilde alleen de onbewerkte leessnelheid testen.

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

Getest in Java 7, 8, 9. Dit was over het algemeen de snelste methode. Het lezen van een bestand van 1 GB duurde altijd iets minder dan 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()

Dit is met succes getest in Java 8 en 9, maar het zal niet werken in Java 7 vanwege het gebrek aan ondersteuning voor lambda-expressies. Het duurde ongeveer 3,5 seconden om een ​​bestand van 1 GB in te lezen, waardoor het op de tweede plaats kwam wat betreft het lezen van grotere bestanden.

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

Getest om te werken in Java 7, 8, 9. Dit duurde ongeveer 4,5 seconden om een ​​testbestand van 1 GB in te lezen.

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

Je kunt hierde volledige ranglijst voor alle 10 bestandsleesmethoden vinden.


Antwoord 6, autoriteit 2%

In Java 8 zou je het volgende kunnen doen:

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

Enkele opmerkingen: de stream die wordt geretourneerd door Files.lines(in tegenstelling tot de meeste streams) moet worden gesloten. Om de redenen hier genoemdvermijd ik het gebruik van forEach(). De vreemde code (Iterable<String>) lines::iteratorwerpt een Stream naar een Iterable.


Antwoord 7, autoriteit 2%

Wat u kunt doen, is de volledige tekst scannen met Scanner en regel voor regel door de tekst gaan.
Natuurlijk moet u het volgende importeren:

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
    }
}

Scanner scant in principe alle tekst. De while-lus wordt gebruikt om door de hele tekst te lopen.

De functie .hasNextLine()is een boolean die true retourneert als er nog meer regels in de tekst staan. De functie .nextLine()geeft je een hele regel als String die je vervolgens kunt gebruiken zoals jij dat wilt. Probeer System.out.println(line)om de tekst af te drukken.

Noot: .txt is de tekst van het bestandstype.


Antwoord 8, autoriteit 2%

FileReader laat je de codering niet specificeren, gebruik in plaats daarvan InputStreamReaderals je het moet specificeren:

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

Als u dit bestand uit Windows hebt geïmporteerd, heeft het mogelijk ANSI-codering (Cp1252), dus u moet de codering opgeven.


Antwoord 9

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

Antwoord 10

In Java 8 is er ook een alternatief voor het gebruik van Files.lines(). Als uw invoerbron geen bestand is, maar iets abstracters, zoals een Readerof een InputStream, kunt u de regels streamenvia de BufferedReaders lines()methode.

Bijvoorbeeld:

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

roept processLine()aan voor elke invoerregel die wordt gelezen door de BufferedReader.


Antwoord 11

U kunt Scannerklasse gebruiken

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

Antwoord 12

Voor het lezen van een bestandmet 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();
        }
    }
}

Antwoord 13

Java 9:

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

Antwoord 14

Je moet de readLine()methode gebruiken in class BufferedReader.
Maak een nieuw object van die klasse en gebruik deze methode op hem en sla het op in een string.

BufferReader Javadoc


Antwoord 15

De duidelijke manier om dit te bereiken,

Bijvoorbeeld:

Als u dataFile.txtin uw huidige directory heeft

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

De uitvoer zoals hieronder,
voer hier de afbeeldingsbeschrijving in


Antwoord 16

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

Het werkt voor mij. Ik hoop dat het jou ook zal helpen.


Antwoord 17

Je kunt streams gebruiken om het nauwkeuriger te doen:

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

Antwoord 18

Ik doe de leesroutine meestal rechttoe rechtaan:

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) {
        }
    }
}

Antwoord 19

Door het org.apache.commons.iopakket te gebruiken, leverde het meer prestaties, vooral in oude code die Java 6 en lager gebruikt.

Java 7 heeft een betere API met minder uitzonderingen
behandeling en meer handige methoden:

LineIterator lineIterator = null;
try {
    lineIterator = FileUtils.lineIterator(new File("/home/username/m.log"), "windows-1256"); // The second parameter is optionnal
    while (lineIterator.hasNext()) {
        String currentLine = lineIterator.next();
        // Some operation
    }
}
finally {
    LineIterator.closeQuietly(lineIterator);
}

Maven

<!-- https://mvnrepository.com/artifact/commons-io/commons-io -->
<dependency>
    <groupId>commons-io</groupId>
    <artifactId>commons-io</artifactId>
    <version>2.6</version>
</dependency>

Antwoord 20

U kunt deze code gebruiken:

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

Antwoord 21

U kunt ook Apache Commons IO:

gebruiken

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

Antwoord 22

U kunt de bestandsgegevens regel voor regel lezen, zoals hieronder:

String fileLoc = "fileLocationInTheDisk";
List<String> lines = Files.lines(Path.of(fileLoc), StandardCharsets.UTF_8).collect(Collectors.toList());

LEAVE A REPLY

Please enter your comment!
Please enter your name here

Other episodes