如何在没有被阻止的情况下以块的形式读取Java中的大文件?

时间:2012-02-01 00:14:42

标签: java multithreading

假设你有一个更大的文件然后你有内存来处理。您希望在此过程中依次读取文件n字节

  • 阅读一个块
  • 将其传递给帖子
  • 阅读另一个块
  • 将其传递给帖子

我尝试了不同的事情并取得了不同的成功,但阻塞似乎总是存在问题。

请提供非阻止方式的示例以获取访问权限,例如byte[]

3 个答案:

答案 0 :(得分:6)

你不能。

等待磁盘为您提供数据时,总是阻止。如果您对每个数据块有很多工作要做,那么使用第二个线程可能有所帮助:该线程可以对数据执行CPU密集型工作,而第一个线程被阻塞,等待下一次读取完成。

但这听起来不像你的情况。

您最好的选择是尽可能大地读取数据(例如,1MB或更多)。这最大限度地减少了内核中阻塞的时间,并且可能导致等待磁盘的时间减少(如果正在读取的块恰好是连续的)。


这是代码

ExecutorService exec = Executors.newFixedThreadPool(1);

// use RandomAccessFile because it supports readFully()
RandomAccessFile in = new RandomAccessFile("myfile.dat", "r");
in.seek(0L);

while (in.getFilePointer() < in.length())
{
    int readSize = (int)Math.min(1000000, in.length() - in.getFilePointer());
    final byte[] data = new byte[readSize];
    in.readFully(data);
    exec.execute(new Runnable() 
    {
        public void run() 
        {
            // do something with data
        }
    });
}

答案 1 :(得分:1)

听起来你正在寻找Streams,缓冲或两者的某种组合(BufferedInputStream任何人?)。

检查一下: http://docs.oracle.com/javase/tutorial/essential/io/buffers.html

这是处理非常大的文件的标准方法。如果这不是你想要的,我道歉,但希望无论如何它都会帮助你流动。

祝你好运!

答案 2 :(得分:0)

如果你有一个执行I / O和CPU计算的程序,如果处理一个字节所花费的CPU时间平均少于读取一个字节的时间,那么阻塞是不可避免的(程序中的某个地方)。

如果您尝试读取文件并且需要磁盘搜索,则数据可能无法到达10毫秒。在这段时间内,2 GHz CPU可以完成20 M个时钟周期的工作。