Java - расщепление большого текстового файла SQL на делиметре с помощью сканера (OutofmemoryError)

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

  •  25-08-2022
  •  | 
  •  

Вопрос

Я пытаюсь написать приложение, которое возьмет на себя очень большой текстовый файл SQL ~ 60 ГБ (257 миллионов строк) и разделить каждое из операторов копирования на отдельные текстовые файлы.

Однако код, который я в настоящее время использую, вызывает OutofmemoryError из -за линий, превышающих предел буфера сканера. Первое заявление будет длиться ~ 40 миллионов строк.

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");
}

Пожалуйста, дайте рекомендации относительно того, является ли это неправильным методом для выполнения этого или изменений в существующем методе.

Спасибо

Это было полезно?

Решение

Во -первых, почему вы создаете или какой -то другой процесс создает файл 60 ГБ! Может быть, вам нужно взглянуть на этот процесс, чтобы исправить этот процесс, чтобы создать меньший текстовый файл 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 вместо сканера. У него также есть удобный метод чтения (), и у меня никогда не было никаких проблем с производительностью. Единственное, что вам нужно вручную проверить, является ли чтение строки, которую вы хотите обработать, но обычно это так же просто, как применение методов класса строк.

Это не ответ на ваш фактический вопрос, но я считаю это приличным простым в использовании альтернативы.

Попробуйте что -то подобное (но красивее):

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

Это украшает все это с помощью буферного читателя, что означает, что не весь содержимое файла будет загружена в память одновременно. Вы можете использовать сканер таким же образом.

Попробуйте использовать BufferedReader. Прямое использование сканера с помощью потоков файлов или необработанных файлов. Подход ставок заключается в том, чтобы использовать BufferedReader и читать по одной строке за раз и выполнять ручные строки и разделить. Если все сделано правильно таким образом, вы можете дать GC достаточно возможности для восстановления памяти, когда это необходимо

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top