目前我正在使用扫描仪/文件阅读器并使用hasnextline。我认为这种方法效率不高。有没有其他方法来读取具有类似功能的文件?
public void Read(String file) {
Scanner sc = null;
try {
sc = new Scanner(new FileReader(file));
while (sc.hasNextLine()) {
String text = sc.nextLine();
String[] file_Array = text.split(" ", 3);
if (file_Array[0].equalsIgnoreCase("case")) {
//do something
} else if (file_Array[0].equalsIgnoreCase("object")) {
//do something
} else if (file_Array[0].equalsIgnoreCase("classes")) {
//do something
} else if (file_Array[0].equalsIgnoreCase("function")) {
//do something
}
else if (file_Array[0].equalsIgnoreCase("ignore")) {
//do something
}
else if (file_Array[0].equalsIgnoreCase("display")) {
//do something
}
}
} catch (FileNotFoundException e) {
System.out.println("Input file " + file + " not found");
System.exit(1);
} finally {
sc.close();
}
}
答案 0 :(得分:32)
您会发现BufferedReader.readLine()
的速度与您的需求一样快:您可以每秒读取数百万行。您的字符串拆分和处理更可能导致您遇到的任何性能问题。
答案 1 :(得分:5)
Scanner
不能像BufferedReader
一样快,因为它使用正则表达式来读取文本文件,这使得它比BufferedReader
慢。通过使用BufferedReader
,您可以从文本文件中读取块。
BufferedReader bf = new BufferedReader(new FileReader("FileName"));
您可以接下来使用readLine()来阅读bf。
希望它符合您的目的。
答案 2 :(得分:4)
我做了gist,比较了不同的方法:
import java.io.*;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Scanner;
import java.util.function.Function;
public class Main {
public static void main(String[] args) {
String path = "resources/testfile.txt";
measureTime("BufferedReader.readLine() into ArrayList", Main::bufferReaderToLinkedList, path);
measureTime("BufferedReader.readLine() into LinkedList", Main::bufferReaderToArrayList, path);
measureTime("Files.readAllLines()", Main::readAllLines, path);
measureTime("Scanner.nextLine() into ArrayList", Main::scannerArrayList, path);
measureTime("Scanner.nextLine() into LinkedList", Main::scannerLinkedList, path);
measureTime("RandomAccessFile.readLine() into ArrayList", Main::randomAccessFileArrayList, path);
measureTime("RandomAccessFile.readLine() into LinkedList", Main::randomAccessFileLinkedList, path);
System.out.println("-----------------------------------------------------------");
}
private static void measureTime(String name, Function<String, List<String>> fn, String path) {
System.out.println("-----------------------------------------------------------");
System.out.println("run: " + name);
long startTime = System.nanoTime();
List<String> l = fn.apply(path);
long estimatedTime = System.nanoTime() - startTime;
System.out.println("lines: " + l.size());
System.out.println("estimatedTime: " + estimatedTime / 1_000_000_000.);
}
private static List<String> bufferReaderToLinkedList(String path) {
return bufferReaderToList(path, new LinkedList<>());
}
private static List<String> bufferReaderToArrayList(String path) {
return bufferReaderToList(path, new ArrayList<>());
}
private static List<String> bufferReaderToList(String path, List<String> list) {
BufferedReader reader;
try {
reader = new BufferedReader(new FileReader(
path));
String line = reader.readLine();
while (line != null) {
line = reader.readLine();
list.add(line);
}
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
return list;
}
private static List<String> readAllLines(String path) {
try {
return Files.readAllLines(Paths.get(path));
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
private static List<String> randomAccessFileLinkedList(String path) {
return randomAccessFile(path, new LinkedList<>());
}
private static List<String> randomAccessFileArrayList(String path) {
return randomAccessFile(path, new ArrayList<>());
}
private static List<String> randomAccessFile(String path, List<String> list) {
try {
RandomAccessFile file = new RandomAccessFile(path, "r");
String str;
while ((str = file.readLine()) != null) {
list.add(str);
}
file.close();
} catch (IOException e) {
e.printStackTrace();
}
return list;
}
private static List<String> scannerLinkedList(String path) {
return scanner(path, new LinkedList<>());
}
private static List<String> scannerArrayList(String path) {
return scanner(path, new ArrayList<>());
}
private static List<String> scanner(String path, List<String> list) {
try {
Scanner scanner = new Scanner(new File(path));
while (scanner.hasNextLine()) {
list.add(scanner.nextLine());
}
scanner.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
}
return list;
}
}
运行:将BufferedReader.readLine()放入ArrayList, 行:1000000, 预计时间:0.105118655
运行:将BufferedReader.readLine()放入LinkedList, 行:1000000, 预计时间:0.072696934
运行:Files.readAllLines(), 行:1000000, 预计时间:0.087753316
运行:将Scanner.nextLine()放入ArrayList, 行:1000000, 预计时间:0.743121734
运行:将Scanner.nextLine()放入LinkedList, 行:1000000, 预计时间:0.867049885
运行:RandomAccessFile.readLine()进入ArrayList, 行:1000000, 预计时间:11.413323046
运行:RandomAccessFile.readLine()进入LinkedList, 行:1000000, 预计时间:11.423862897
BufferedReader
最快,Files.readAllLines()
也可以接受,Scanner
由于正则表达式而较慢,RandomAccessFile
不可接受
答案 3 :(得分:2)
您可以使用JAVA NIO中的FileChannel和ByteBuffer。 ByteBuffer大小是我观察到的更快读取数据的最关键部分。 下面的代码将读取文件的内容。
static public void main( String args[] ) throws Exception
{
FileInputStream fileInputStream = new FileInputStream(
new File("sample4.txt"));
FileChannel fileChannel = fileInputStream.getChannel();
ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
fileChannel.read(byteBuffer);
byteBuffer.flip();
int limit = byteBuffer.limit();
while(limit>0)
{
System.out.print((char)byteBuffer.get());
limit--;
}
fileChannel.close();
}
您可以在此处检查新行的'\ n'。感谢。
即使你可以分散和获取更快速读取文件的方式,即
fileChannel.get(buffers);
其中
ByteBuffer b1 = ByteBuffer.allocate(B1);
ByteBuffer b2 = ByteBuffer.allocate(B2);
ByteBuffer b3 = ByteBuffer.allocate(B3);
ByteBuffer[] buffers = {b1, b2, b3};
这样可以避免用户进程进行多次系统调用(这可能很昂贵)并允许内核优化数据处理,因为它有关于总传输的信息,如果有多个CPU可用,甚至可以填充和同时排出几个缓冲区。
来自this本书。
答案 4 :(得分:0)
您必须调查程序的哪个部分需要时间。
根据EJP的回答,你应该使用BufferedReader。
如果真正的字符串处理花费时间,那么你应该考虑使用线程,一个线程将从文件和队列行读取。其他字符串处理器线程将使队列出列并处理它们。您需要调查要使用的线程数,应该在应用程序中使用的线程数必须与CPU中的核心数相关联,这样就会使用完整的CPU。
答案 5 :(得分:0)
使用BufferedReader进行高性能文件访问。但是默认缓冲区大小为8192字节通常太小。对于大文件,您可以increase the buffer size按数量级来提高文件读取性能。例如:
BufferedReader br = new BufferedReader("file.dat", 1000 * 8192);
while ((thisLine = br.readLine()) != null) {
System.out.println(thisLine);
}
答案 6 :(得分:0)
仅更新此线程,现在我们有Java 8可以完成此工作:
List<String> lines = Files.readAllLines(Paths.get(file_path);
答案 7 :(得分:-1)
如果您希望一起阅读所有行,那么您应该查看java 7的Files API。它非常简单易用。
但更好的方法是批量处理此文件。让读者从文件中读取大量的行,并使用编写器执行所需的处理或持久化数据。即使生产线在未来增加到十亿,它也将确保它能够正常运转。您还可以使用多线程批处理来提高批处理的整体性能。我建议你看一下春季批次。