RandomAccessFile和读/写开始 - 结束位置

时间:2011-03-12 06:00:37

标签: java

我搜索了很多但仍然找不到......所以我希望你能帮我理解:)

问题是......

我有大文件A.dat,我想要

  • A)用RandomAccessFile读取它(到 避免OutOfMemory错误)
  • B)用4Mb(缓冲区)
  • 读取
  • C)将每个4Mb的文件写入文件 B.dat
  • D)所以把文件B.dat作为副本 文件A.dat

但是我有一个问题......如果我有一个文件的长度不能被4Mb分开,数据会丢失并且文件被损坏:(

例如...... 我有媒体文件。它的长度是15.8Mb,所以我只能得到15.8Mb / 4Mb = 3整件。然后我只能写那3个字节的片断,其余的丢失:( 或者问题是文件是否小于缓冲区大小(4Mb)......

我认为这不应该是一项艰巨的任务,但我看不出任何标准教程如何解决这类问题......

我非常希望你能帮我解决这个问题。

1 个答案:

答案 0 :(得分:1)

在这种情况下,RandomAccessFile似乎没有用处。使用传统的基于流的I / O是最好的,除非你做错了,否则肯定不会导致内存不足。这里真的是你需要的所有代码(未经测试):

InputStream in = null;
OutputStream out = null;
try {
    in = new FileInputStream("a.dat");
    out = new FileInputStream("b.dat");
    byte[] buffer = new byte[4*1024*1042]; //4 MiB
    for ( int len = 0; (len = in.read(buffer)) != -1; ) {
       out.write(buffer, 0, len);
    }
} finally {
    if ( in != null )
       try { in.close() } catch (IOException ignore) {}
    if ( out != null )
       try { out.close() } catch (IOException ignore) {}
}

如果您因某种原因确实需要RandomAccessFile而无法告诉我们,该方法基本相同。使用RandomAccessFile.read(byte[], int, int)的结果找出实际读入缓冲区的数据量,并使用该数字来限制写回输出文件的数量。

修改

以上需要一些解释。以下是关键部分:

    byte[] buffer = new byte[4*1024*1042]; //4 MiB

这会初始化一个4个二进制兆字节的字节数组,一次只能容纳一个文件块。

    for ( int len = 0; 

在for循环中,我们首先声明一个值len,它将记录我们读入的字节数。

(len = in.read(buffer)) != -1; 

然后我们在read上调用InputStream。这会将字节读入字节数组,直到缓冲区已满,或者没有剩余数据要读取(到达文件末尾)。此方法返回实际读取的字节数,并将其分配给len。如果该值为-1,则表示流已关闭,因此我们退出循环。

) {
   out.write(buffer, 0, len);
}

然后,对于我们读过的每个块,我们将其写入输出流。 buffer表示我们要从字节数组中写入,0表示我们想要从数组的开头开始,len表示要写入多少字节。请记住,如果我们的缓冲区未填充,那么len将被相应地设置,并且只会写入数组的一部分。

我给你的是惯用版本,可能更难以遵循。这是一种更直接的方式来做同样的事情:

int numberOfBytesRead;
while ( true ) {
   numberOfBytesRead = in.read(buffer); //read bytes into buffer
if ( numberOfBytesRead == -1 ) break; //end of stream
   out.write(buffer, 0, numberOfBytesRead); //write the same # of bytes we read
}