0

現在、約3万行のテキストファイルを読み込もうとしています。

私はどのように読んでいますか?

java.io.BufferedReader を使用して読んでいます

これは、私のアプローチを表す小さなコード スニペットです。

int lineNumber = 1;
BufferedReader br = null;
String currentLine = null;
br = new BufferedReader(new FileReader(f));//here f will be the file name to be read, I have passed
while ((cuurentLine = br.readLine()) != null) {
  //here I have written logic to do processing after reading 1000 lines
  //line number = 1001 start processing, similarly it reads next 1000 lines, each line is put in a List collection
  //after reaching 1001 line clearing list and continuing the loop
}

次のケースでNIO2を使用してみました

br = Files.newBufferedReader(Paths.get(inputFileName), StandardCharsets.UTF_16);

次の例外が発生しました

exception :Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
    at java.util.Arrays.copyOf(Unknown Source)
    at java.lang.AbstractStringBuilder.expandCapacity(Unknown Source)
    at java.lang.AbstractStringBuilder.ensureCapacityInternal(Unknown Source)
    at java.lang.AbstractStringBuilder.append(Unknown Source)
    at java.lang.StringBuffer.append(Unknown Source)
    at java.io.BufferedReader.readLine(Unknown Source)
    at java.io.BufferedReader.readLine(Unknown Source)
    at TexttoExcelMerger.readFileLineByLine(TexttoExcelMerger.java:66)
    at TexttoExcelMerger.main(TexttoExcelMerger.java:255)

まず、私のアプローチは正しいですか?

NIO2、apache FileUtils、またはファイルをより速く読み取るための他の API に効率的で高速なアプローチはありますか?これにより、ファイルの読み取りプロセスが高速化されます。のよう
br.readFirst(1000);に最初の 1000 行のセットを読み取ることができます
が、ロジックのように行ごとに読み取ったり反復したりする必要はありません。

4

2 に答える 2

2

ファイル全体をメモリに読み込むアプローチは、失敗する運命にあります。遅かれ早かれ、ファイルが使用可能なメモリを超え、プログラムが機能しなくなり、完全に再設計する必要があります。その間、ユーザーができることは何もないため、適切な失敗モードではありません。あなたはその時点でmowです。何十万行もあるファイルで試してみようというのは、かなり野心的でしたね。一度に1行ずつ再考して処理します。またはデータベースを使用します。

注意:自分をからかわないでください。ファイルの読み取りに java.io を使用しています。ここでの NIO2 コンポーネントは最小限です。まったく必要ないというわけではありません。

于 2013-05-20T12:41:05.530 に答える
2

メモリ不足の例外

大量のファイルをメモリに読み込もうとしているため、メモリが不足しています。これは、私が考えることができる2つの方法で起こっている可能性があります。

わざとやってるだろ

読み込んだすべての行を保存しようとすると、メモリが不足します。

while ((curentLine = br.readLine()) != null) {
    stringBuilder.append(currentLine);
}

一度に 1000 行を節約しようとしているだけなら、Java のヒープ サイズを増やすだけで問題ないかもしれません-Xmx。それはすべて、1000行が占めるメモリの量に依存します。

うっかりやってるだろ

読み込んでいるファイルに改行がない場合、 はそれbr.readLine()が 1 つの巨大な長い行であると信じて、全体を読み込もうとします。

行ごとに行かずに読む

任意のテキスト ファイルを想像すると、それは単なる長い文字列です。これらの文字 ( EOL) の一部は、人間や多くのプログラムにとって特別な意味を持ちますが、それでも単なる文字です。これは、その前にあるすべての文字を読まずに「テキストの 10 行目をください」とだけ言うことはできないことを意味します (なぜなら、どの文字EOLを数える必要があるのか​​ わからないからです)。

固定長のレコード形式を使用できます。各行は正確に $n$ 文字だけ (80 など) になると言います。10 行目にジャンプしたい場合は、800 文字目にジャンプできます。しかし、実際に UTF-16 を使用している場合、文字は ではなく、実際にcharは機能しません。

おそらくこの時点でデータベースを使用しているはずなので、問題ありません。

于 2013-05-20T13:03:31.140 に答える