14

我必须逐个字符地读取一个 53 MB 的文件。当我使用 ifstream 在 C++ 中执行此操作时,它会在几毫秒内完成,但使用 Java InputStream 则需要几分钟。Java 这么慢是正常的还是我错过了什么?

此外,我需要用 Java 完成程序(它使用 servlet,我必须从中调用处理这些字符的函数)。我在想也许用 C 或 C++ 编写文件处理部分,然后使用 Java Native Interface 将这些函数与我的 Java 程序接口......这个想法如何?

谁能给我任何其他提示...我真的需要更快地阅读文件。我尝试使用缓冲输入,但它仍然没有提供接近 C++ 的性能。

编辑:我的代码跨越了几个文件,而且很脏,所以我给出了概要

import java.io.*;

public class tmp {
    public static void main(String args[]) {
        try{
        InputStream file = new BufferedInputStream(new FileInputStream("1.2.fasta"));
        char ch;        
        while(file.available()!=0) {
            ch = (char)file.read();
                    /* Do processing */
            }
        System.out.println("DONE");
        file.close();
        }catch(Exception e){}
    }
}
4

4 回答 4

15

我用一个 183 MB 的文件运行了这段代码。它打印“Elapsed 250 ms”。

final InputStream in = new BufferedInputStream(new FileInputStream("file.txt"));
final long start = System.currentTimeMillis();
int cnt = 0;
final byte[] buf = new byte[1000];
while (in.read(buf) != -1) cnt++;
in.close();
System.out.println("Elapsed " + (System.currentTimeMillis() - start) + " ms");
于 2012-05-06T20:36:29.283 回答
3

我会试试这个

// create the file so we have something to read.
final String fileName = "1.2.fasta";
FileOutputStream fos = new FileOutputStream(fileName);
fos.write(new byte[54 * 1024 * 1024]);
fos.close();

// read the file in one hit.
long start = System.nanoTime();
FileChannel fc = new FileInputStream(fileName).getChannel();
ByteBuffer bb = fc.map(FileChannel.MapMode.READ_ONLY, 0, fc.size());
while (bb.remaining() > 0)
    bb.getLong();
long time = System.nanoTime() - start;
System.out.printf("Took %.3f seconds to read %.1f MB%n", time / 1e9, fc.size() / 1e6);
fc.close();
((DirectBuffer) bb).cleaner().clean();

印刷

Took 0.016 seconds to read 56.6 MB
于 2012-05-06T20:42:08.987 回答
2

使用BufferedInputStream

InputStream buffy = new BufferedInputStream(inputStream);
于 2012-05-06T20:14:50.613 回答
1

如上所述,使用 BufferedInputStream。你也可以使用 NIO 包。请注意,对于大多数文件,BufferedInputStream 的读取速度与 NIO 一样快。但是,对于非常大的文件,NIO 可能会做得更好,因为您可以进行内存映射文件操作。此外,NIO 包执行可中断 IO,而 java.io 包则没有。这意味着如果你想从另一个线程取消操作,你必须使用 NIO 来使其可靠。

ByteBuffer buf = ByteBuffer.allocate(BUF_SIZE);
FileChannel fileChannel = fileInputStream.getChannel();
int readCount = 0;
while ( (readCount = fileChannel.read(buf)) > 0) {
  buf.flip();
  while (buf.hasRemaining()) {
    byte b = buf.get();
  }
  buf.clear();
}
于 2012-05-06T20:35:13.310 回答