Java-使用扫描仪(OutofMemoryError)在分隔线上分配大型SQL文本文件

StackOverflow https://stackoverflow.com/questions/20353915

  •  25-08-2022
  •  | 
  •  

我正在尝试编写一个应用程序,该应用程序将使用一个非常大的SQL文本文件〜60GB(2.57亿行),并将每个复制语句分为单独的文本文件。

但是,由于超过扫描仪缓冲区限制的线,我目前正在使用的代码会导致欧元欧洲。第一个声明将为约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");
}

请提供有关这是执行此方法还是对现有方法更改的方法的建议。

谢谢

有帮助吗?

解决方案

首先,为什么要创建或其他一些过程创建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();

其他提示

我个人:我使用BufferedReader代替扫描仪。它还具有方便的readline()方法,并且我从未遇到过任何性能问题。唯一的事情是您需要手动检查行读数是否是要处理的行,但这通常与应用字符串类方法一样简单。

这不是您实际问题的答案,但我认为这是一个易于使用的替代方案。

尝试这样的事情(但更漂亮):

Scanner sc = new Scanner(new BufferedReader(new FileReader(file)));

这用BufferedReader装饰了整个内容,这意味着并非所有文件的内容都会一次加载到内存中。您可以以相同的方式使用扫描仪。

尝试使用BufferedReader。直接使用扫描仪与文件或原始文件流woudl加载数据中的数据,并不会在GC上刷新它。 BETS方法是使用BufferedReader并一次读取一行,并进行手动字符串检查和分裂。如果这样做正确,您可以给GC足够的机会在需要时回收内存

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top