6

150k レコードのデータベースがあります。これをできるだけ早くファイルに書き込みたい。私は多くのアプローチを試しましたが、すべてが遅いようです。これをより速くするにはどうすればよいですか?

これらのレコードを 40k のブロックで読み取りました。最初に 40k を読み取り、次に別の 40k を読み取ります。

レコードを読み取った後、このプロセスは 40,000 行を含む StringBuilder を返します。次に、この StringBuilder をファイルに書き込みます。

private static void write(StringBuilder sb, Boolean append) throws Exception {
    File file = File.createTempFile("foo", ".txt");

    FileWriter writer = new FileWriter(file.getAbsoluteFile(), append);
    PrintWriter out = new PrintWriter(writer);
    try {
        out.print(sb);           
        out.flush();
        writer.flush();
    } finally {
        writer.close();
        out.close();
    }
}

私はこの他の例を読みましたが、それは同様に遅いです:テキストファイル Java に巨大なデータを書き込む最速の方法

私もNIO APIで試しました:

private static void write(StringBuilder sb, Boolean append)) throws Exception {
    FileChannel rwChannel = new FileOutputStream("textfile.txt", true).getChannel();
    ByteBuffer bb = ByteBuffer.wrap(sb.toString().getBytes("UTF-8"));
    rwChannel.write(bb);
    rwChannel.close();
}

巨大なデータをファイルに書き込む/追加する最良の方法はどれですか?

4

5 に答える 5

8

ここは必要ありませんPrintWriter。なんらかの種類Writer(たとえば a FileWriter) がある場合は、単純にそれを呼び出すことができますappend(sb)。そして、する必要はありません、フラッシュすることflushを意味します。close

private static void write(StringBuilder sb, Boolean append) throws Exception {
  File file = File.createTempFile("foo", ".txt");

  try(FileWriter writer = new FileWriter(file.getAbsoluteFile(), append)) {
      writer.append(sb);
  }
}

私のシステムでは、Channelではなく を使用してパフォーマンスがわずかに向上しましたOutputStream

private static void write0a(StringBuilder sb, Boolean append) throws Exception {
  File file = File.createTempFile("foo", ".txt");

  try(Writer writer = Channels.newWriter(new FileOutputStream(
      file.getAbsoluteFile(), append).getChannel(), "UTF-8")) {
    writer.append(sb);
  }
}

ただし、これらはわずかな改善にすぎません。すべてのコードが同じルーチンを呼び出すことになるため、ここでは多くの可能性が見られません。パフォーマンスを本当に改善できるのは、呼び出し中にライターを維持し、すべてのレコードをフラッシュしないことです。

于 2013-09-10T14:13:16.307 に答える
5

膨大な量のデータがある場合は、StringBuilder に保存してから一度にファイルに書き込むのではなく、より良い方法です。

これが最良のシナリオです。

1) データの処理を開始する前に、FileInputStream を作成します。

FileOutputStream fos = new FileOutputStream("/path/of/your/file");

2)このファイルからStreamWriterを作成して出力します

OutputStreamWriter w = new OutputStreamWriter(fos, "UTF-8");

3) BufferedWriter を作成する (ファイル書き込みのパフォーマンスを向上させる)

BufferedWriter bw = new BufferedWriter(w);

4) bw をプロセス関数に渡してから、フラッシュ/クローズします。

bw.flush();
bw.close();

StringBuilder と BufferedWriter の機能はほとんど同じなので、コードをそれほど変更する必要はありません。このシナリオの唯一のマイナス点は、データがファイルに書き込まれている間ずっとプロセスに関与することですが、別のスレッドでデータを処理しなければ問題にはなりません。

このように、データがどれほど大きいかは問題ではありません

于 2013-09-10T12:39:29.230 に答える
-1

Apache IO を試してみましたが、パフォーマンスは同じですか?

于 2013-09-10T12:55:56.110 に答える