我正在尝试编写一个应用程序,它将占用一个非常大的sql文本文件~60GB(2.57亿行),并将每个COPY语句拆分成单独的文本文件。
但是,由于线路超出了扫描器缓冲区限制,我当前使用的代码会导致OutOfMemoryError。第一个声明将是大约4000万行。
public static void readFileByDelimeter(String fileName, String requestType, String output) throws FileNotFoundException {
//creating file instance
File file = new File(fileName);
//create scanner instance
Scanner scanner = new Scanner(file, "latin1");
//set custom delimeter
scanner.useDelimeter("COPY");
int number = 0;
System.out.println("Running......");
while (scanner.hasNext()){
String line = scanner.next();
if (line.length() > 20) {
//save statements to seperate SQL files
PrintWriter out = new PrintWriter("statement" + number + ".sql");
out.println("COPY" + line.trim());
out.close();
}
number++;
}
System.out.println("Completed");
}
请提供建议,以确定这是否是执行此方法或更改现有方法的错误方法。
由于
答案 0 :(得分:0)
我个人:我使用BufferedReader而不是Scanner。它还有一个方便的readLine()方法,我从来没有遇到任何性能问题。唯一的事情是你需要手动检查行读是否是你想要处理的行,但这通常就像应用String类方法一样简单。
这不是你实际问题的答案,但我认为这是一个容易使用的替代方案。
答案 1 :(得分:0)
尝试这样的事情(但更漂亮):
Scanner sc = new Scanner(new BufferedReader(new FileReader(file)));
这使用BufferedReader来装饰整个事物,这意味着并非所有文件的内容都会立即加载到内存中。您可以以相同的方式使用扫描仪。
答案 2 :(得分:0)
尝试使用BufferedReader。直接使用带有文件或原始文件流的扫描程序会将数据加载到内存中,并且不会在GC上将其清除。 Bets方法是使用BufferedReader并一次读取一行并进行手动字符串检查和拆分。如果以这种方式正确完成,您可以为GC提供足够的机会在需要时回收内存
答案 3 :(得分:0)
首先,为什么要创建或其他一些进程正在创建60GB文件!也许您需要查看该过程来修复该过程以生成较小的sql文本文件,而不是创建新进程。但是,如果这是你需要做的一次性事情,那么可能没问题但是为了解决你的问题,我会使用BufferedReader来读取和处理记录,如果它是你指示的大文件。
BufferedReader br = new BufferedReader(new FileReader(file));
String line;
while ((line = br.readLine()) != null) {
// process the line. and write into your output file and close the file.
}
br.close();