Java-スキャナー(outofmemoryError)を使用して、デリメーター上の大きなSQLテキストファイルを分割する

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

  •  25-08-2022
  •  | 
  •  

質問

私は、非常に大きなSQLテキストファイル〜60GB(2億5700万行)を取得し、各コピーステートメントを別のテキストファイルに分割するアプリケーションを書き込もうとしています。

ただし、私が現在使用しているコードは、スキャナーバッファーの制限を超える線があるため、OutOfMemoryErrorを引き起こします。最初の声明は、長さ4,000万行になるでしょう。

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ファイルを作成しているのか!新しいプロセスを作成する代わりに、そのプロセスを修正するためにそのプロセスを修正するためにそのプロセスを修正する必要があるかもしれません。ただし、これが必要なことが1回である場合、それは問題ないかもしれませんが、あなたの質問に対処するために、あなたが示したように大きなファイルの場合、レコードを読んで処理するために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でフラッシュすることはできません。 BETSアプローチは、BufferedReaderを使用して、一度に1行ずつ読み取り、手動の文字列チェックと分割を行うことです。この方法で正しく行われた場合、必要に応じてメモリを取り戻すのに十分な機会をGCに与えることができます

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top