我搜索了很多但仍然找不到......所以我希望你能帮我理解:)
问题是......
我有大文件A.dat,我想要
但是我有一个问题......如果我有一个文件的长度不能被4Mb分开,数据会丢失并且文件被损坏:(
例如...... 我有媒体文件。它的长度是15.8Mb,所以我只能得到15.8Mb / 4Mb = 3整件。然后我只能写那3个字节的片断,其余的丢失:( 或者问题是文件是否小于缓冲区大小(4Mb)......
我认为这不应该是一项艰巨的任务,但我看不出任何标准教程如何解决这类问题......
我非常希望你能帮我解决这个问题。
答案 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
}