4

私は約4MBのファイルを持っています。ファイルは通常のキーボード文字のみを含むASCIIファイルです。java.ioパッケージの多くのクラスを試して、ファイルの内容を文字列として読み取りました。(FileReaderとBufferedReaderを使用して)文字ごとに読み取るには約40秒かかり、java.nioパッケージ(FileChannelとByteBuffer)を使用してコンテンツを読み取るには約25秒かかります。これは私の知識から少し長い時間です。誰かがこの時間の消費を約10秒に減らす方法を知っていますか?Cを使用してファイルリーダーを作成したり、Javaから呼び出したりするようなソリューションでもかまいません。以下のスニペットを使用して、4MBのファイルを22秒で読み取りました-

public static String getContents(File file) {
    try {
        if (!file.exists() && !file.isFile()) {
            return null;
        }
        FileInputStream in = new FileInputStream(file);
        FileChannel ch = in.getChannel();
        ByteBuffer buf = ByteBuffer.allocateDirect(512);            
        Charset cs = Charset.forName("ASCII");          
        StringBuilder sb = new StringBuilder();
        int rd;
        while ((rd = ch.read(buf)) != -1) {
            buf.rewind();
            CharBuffer chbuf = cs.decode(buf);
            for (int i = 0; i < chbuf.length(); i++) {
                sb.append(chbuf.get());
            }
            buf.clear();
        }
        String contents = sb.toString();
        System.out.println("File Contents:\n"+contents);
        return contents;
    } catch (Exception exception) {
        System.out.println("Error:\n" + exception.getMessage());
        return null;
    }
}
4

3 に答える 3

5

あなたのハードウェアが何であるか想像できませんが、4MBのファイルの場合は0.1秒未満かかるはずです。

ファイルを一度に読み取る高速な方法は、ファイルをbyte[]に読み込むことです。

public static String readFileAsString(File file) {
    try {
        DataInputStream in = new DataInputStream(FileInputStream(file));
        byte[] bytes = new byte[(int) file.length()];
        in.readFully(bytes);
        in.close();
        return new String(bytes, 0); // ASCII text only.

    } catch (FileNotFoundException e) {
        return null;
    } catch (IOException e) {
        System.out.println("Error:\n" + e.getMessage());
        return null;
    }
}

public static void main(String... args) throws IOException {
    File tmp = File.createTempFile("deleteme", "txt");
    tmp.deleteOnExit();

    byte[] bytes = new byte[4 * 1024 * 1024];
    Arrays.fill(bytes, (byte) 'a');
    FileOutputStream fos = new FileOutputStream(tmp);
    fos.write(bytes);
    fos.close();

    long start = System.nanoTime();
    String s = readFileAsString(tmp);
    long time = System.nanoTime() - start;
    System.out.printf("Took %.3f seconds to read a file with %,d bytes%n",
            time / 1e9, s.length());
}

プリント

Took 0.026 seconds to read a file with 4,194,304 bytes

ファイルをさらに高速に読み取りたい場合は、メモリマップトファイルを使用することをお勧めします。10ミリ秒未満で完了しますが、この場合はオーバーキルです。

于 2012-04-10T11:09:58.780 に答える
2
  1. ここで直接バイトバッファを使用する利点はありません。
  2. 512のバッファサイズが小さすぎます。少なくとも4096を使用してください。
  3. ここでNIOを使用することに実際のメリットはありません。これはテキストなので、BufferedReaderを使用します。
  4. ファイル全体をメモリに読み込むという基本的な目的には欠陥があります。スケーリングせず、すでに過剰な量のメモリを使用しています。ファイルを一度に1行ずつ処理するための戦略を考案する必要があります。
于 2012-04-11T00:36:51.077 に答える
1

バッファサイズを増やすことができます。たとえば、2048バイトまたは4096バイトに増やすことができます。

コンパイル時の型チェックなどのJava機能を利用できないため、ネイティブAPIを使用しないでください。

于 2012-04-10T11:10:56.720 に答える