Ich muss zeilenweise eine große Textdatei von 5-6 GB mit Java lesen.
Wie kann ich das schnell machen?
Ein übliches Muster ist zu verwenden
try (BufferedReader br = new BufferedReader(new FileReader(file))) {
String line;
while ((line = br.readLine()) != null) {
// process the line.
}
}
Sie können die Daten schneller lesen, wenn Sie davon ausgehen, dass keine Zeichencodierung vorliegt. z.B. ASCII-7 macht aber keinen großen Unterschied. Es ist sehr wahrscheinlich, dass das, was Sie mit den Daten machen, viel länger dauern wird.
BEARBEITEN: Ein weniger übliches Muster, das den Umfang von line
undicht macht.
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 ist das möglich
try (Stream<String> stream = Files.lines(Paths.get(fileName))) {
stream.forEach(System.out::println);
}
HINWEIS: Sie müssen den Stream in einem try-with-resource -Block platzieren, um sicherzustellen, dass die #close-Methode für ihn aufgerufen wird. Andernfalls wird der zugrunde liegende Dateihandle nie geschlossen, bis GC dies später ausführt.
Schau dir diesen Blog an:
Die Puffergröße kann angegeben werden oder Die Standardgröße kann verwendet werden. Das Die Standardeinstellung ist groß genug für die meisten Zwecke.
// 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();
Sobald Java-8 out ist (März 2014), können Sie Streams verwenden:
try (Stream<String> lines = Files.lines(Paths.get(filename), Charset.defaultCharset())) {
lines.forEachOrdered(line -> process(line));
}
Alle Zeilen in der Datei drucken:
try (Stream<String> lines = Files.lines(file, Charset.defaultCharset())) {
lines.forEachOrdered(System.out::println);
}
Hier ist ein Beispiel mit vollständiger Fehlerbehandlung und Unterstützung der Zeichensatzspezifikation für Pre-Java 7. Mit Java 7 können Sie die try-with-resources-Syntax verwenden, die den Code sauberer macht.
Wenn Sie nur den Standardzeichensatz wünschen, können Sie den InputStream überspringen und FileReader verwenden.
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 ist die Groovy-Version mit vollständiger Fehlerbehandlung:
File f = new File("textfile.txt");
f.withReader("UTF-8") { br ->
br.eachLine { line ->
println line;
}
}
In Java 8 können Sie Folgendes tun:
try (Stream<String> lines = Files.lines (file, StandardCharsets.UTF_8))
{
for (String line : (Iterable<String>) lines::iterator)
{
;
}
}
Einige Hinweise: Der von Files.lines
(im Gegensatz zu den meisten Streams) zurückgegebene Stream muss geschlossen werden. Aus den Gründen hier erwähnt vermeide ich die Verwendung von forEach()
. Der seltsame Code (Iterable<String>) lines::iterator
wandelt einen Stream in eine Iterable um.
Sie können den gesamten Text mit dem Scanner scannen und den Text Zeile für Zeile durchgehen. __ Natürlich sollten Sie Folgendes importieren:
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
}
}
Der Scanner scannt grundsätzlich den gesamten Text. Die while-Schleife wird verwendet, um den gesamten Text zu durchlaufen.
Die Funktion .hasNextLine()
ist ein boolescher Wert, der true zurückgibt, wenn der Text noch mehr Zeilen enthält. Die Funktion .nextLine()
gibt Ihnen eine gesamte Zeile als String, die Sie dann wie gewünscht verwenden können. Versuchen Sie System.out.println(line)
, um den Text zu drucken.
Anmerkung: .txt ist der Dateityptext.
FileReader lässt Sie die Kodierung nicht angeben. Verwenden Sie InputStreamReader
instead, wenn Sie sie angeben müssen:
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();
}
Wenn Sie diese Datei aus Windows importiert haben, verfügt sie möglicherweise über eine ANSI-Codierung (Cp1252). Daher müssen Sie die Codierung angeben.
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);
}
Ich dokumentierte und testete 10 verschiedene Arten, eine Datei in Java zu lesen und führte sie dann gegeneinander aus, indem sie in Testdateien von 1 KB bis 1 GB eingelesen wurden. Hier sind die schnellsten 3 Datei-Lesemethoden zum Lesen einer 1 GB-Testdatei.
Beachten Sie, dass ich beim Ausführen der Leistungstests nichts an die Konsole ausgegeben habe, da dies den Test wirklich verlangsamen würde. Ich wollte nur die rohe Lesegeschwindigkeit testen.
1) Java.nio.file.Files.readAllBytes ()
Getestet in Java 7, 8, 9. Dies war insgesamt die schnellste Methode. Das Lesen einer 1 GB-Datei dauerte konstant knapp 1 Sekunde.
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 ()
Dies wurde in Java 8 und 9 erfolgreich getestet, funktioniert jedoch in Java 7 nicht, da keine Lambda-Ausdrücke unterstützt werden. Es dauerte etwa 3,5 Sekunden, um eine 1 GB-Datei einzulesen, was den zweiten Platz beim Lesen größerer Dateien einnimmt.
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
Getestet, um in Java 7, 8, 9 zu arbeiten. Das Einlesen einer 1 GB-Testdatei dauerte etwa 4,5 Sekunden.
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);
}
}
}
Sie finden die vollständigen Rankings für alle 10 Methoden zum Lesen von Dateien hier .
Zum Lesen der Datei mit 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();
}
}
}
Sie können die Scanner-Klasse verwenden
Scanner sc=new Scanner(file);
sc.nextLine();
In Java 8 gibt es auch eine Alternative zur Verwendung von Files.lines()
. Wenn Ihre Eingabequelle keine Datei ist, sondern etwas abstrakteres wie eine Reader
oder eine InputStream
, können Sie die Zeilen mit der Methode BufferedReader
s lines()
stream.
Zum Beispiel:
try( BufferedReader reader = new BufferedReader( ... ) ) {
reader.lines().foreach( line -> processLine( line ) );
}
ruft processLine()
für jede von der BufferedReader
gelesene Eingabezeile auf.
Sie müssen die readLine()
-Methode in class BufferedReader
..__ verwenden. Erstellen Sie ein neues Objekt aus dieser Klasse und verwenden Sie diese Methode für ihn, und speichern Sie es in einer Zeichenfolge.
try (Stream<String> stream = Files.lines(Paths.get(fileName))) {
stream.forEach(System.out::println);
}
Der klare Weg, dies zu erreichen,
Zum Beispiel:
Wenn Sie dataFile.txt
in Ihrem aktuellen Verzeichnis haben
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();
}
}
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");
}
Für mich geht das. Hoffe es wird dir auch helfen.
Normalerweise mache ich die Lese-Routine unkompliziert:
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) {
}
}
}
durch die Verwendung vonorg.Apache.commons.iopackage wurde die Leistung insbesondere in älterem Code verbessert, der Java 6 und darunter verwendet.
Java7 hat eine bessere API mit weniger Ausnahmen Und mehr nützliche Methoden
LineIterator lineIterator =null;
try{
lineIterator = FileUtils.lineIterator(new File("/home/username/m.log"), "windows-1256");//second parameter is optionanl
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>
Sie können Streams verwenden, um es genauer zu machen:
Files.lines(Paths.get("input.txt")).forEach(s -> stringBuffer.append(s);
Sie können auch Apache commons io
verwenden:
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();
}
Sie können diesen Code verwenden:
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();
}
}
}