Java- 스캐너를 사용하여 구분 제로 큰 SQL 텍스트 파일 분할 (OutofMemoryError)

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

  •  25-08-2022
  •  | 
  •  

문제

매우 큰 SQL 텍스트 파일 ~ 60GB (2 억 5,700 만 줄)를 가져갈 응용 프로그램을 작성하고 각 사본 문을 별도의 텍스트 파일로 분할하려고합니다.

그러나 현재 사용중인 코드는 스캐너 버퍼 한계를 초과하는 선으로 인해 OutofMemoryError를 유발합니다. 첫 번째 진술은 4 천만 줄의 길이가 될 것입니다.

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를 사용해보십시오. 파일 또는 원시 파일 스트림과 함께 스캐너를 직접 사용하여 메모리에 데이터를로드하여 GC에서 플러시하지 않습니다. 베팅 접근 방식은 BufferedReader를 사용하고 한 번에 한 줄을 읽고 수동 문자열 검사 및 분할을 수행하는 것입니다. 이 방법으로 올바르게 수행하면 GC에 필요할 때 메모리를 되 찾을 수있는 충분한 기회를 줄 수 있습니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top