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 line
lekt.
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::iterator
werpt 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 InputStreamReader
als 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 Reader
of een InputStream
, kunt u de regels streamenvia de BufferedReader
s 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.
Antwoord 15
De duidelijke manier om dit te bereiken,
Bijvoorbeeld:
Als u dataFile.txt
in 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();
}
}
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());