Java - 使用扫描程序在分隔符上拆分大型SQL文本文件(OutOfMemoryError)

时间:2013-12-03 14:31:53

标签: java sql text

我正在尝试编写一个应用程序,它将占用一个非常大的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");
}

请提供建议,以确定这是否是执行此方法或更改现有方法的错误方法。

由于

4 个答案:

答案 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();