简体   繁体   English

RandomAccessFile和读/写开始完成位置

[英]RandomAccessFile and read/write start-finish position

I've searched this a lot but still can't find... So I hope you can help me to understand :) 我已经搜索了很多,但仍然找不到...所以希望您能帮助我理解:)

The question is... 问题是...

I have big file A.dat and I want 我有大文件A.dat,我想要

  • A) Read it with RandomAccessFile (to avoid OutOfMemory error) A)用RandomAccessFile读取它(以避免OutOfMemory错误)
  • B) Read it by pieces of 4Mb (buffer) B)读取4Mb片段(缓冲区)
  • C) Write each this 4Mb piece to file B.dat C)将每个4Mb片段写入文件B.dat
  • D) So to make file B.dat as a copy of file A.dat D)因此,将文件B.dat复制为文件A.dat

But I have a problem... If I have a file which length cannot be devided by 4Mb the data get lost and file become corrupted :( 但是我有一个问题...如果我有一个文件长度不能由4Mb划分,则数据会丢失并且文件会损坏:(

For example... I have media file. 例如...我有媒体文件。 Its length is 15.8Mb so I can get only 15.8Mb/4Mb=3 whole pieces. 它的长度是15.8Mb,所以我只能得到15.8Mb / 4Mb = 3整块。 Then I can write only those 3 bytes pieces and the rest get lost :( Or the problem is if file is smaller than buffer size (4Mb)... 然后我只能写那3个字节的片段,其余的会丢失:(或问题是如果文件小于缓冲区大小(4Mb)...

I think it shouldn't be a hard task but I couldn't see any standart tutorial which shows how to solve such kind of things... 我认为这不应该是一项艰巨的任务,但我看不到任何标准的教程来展示如何解决这类问题...

I dearly hope you can help me with this question. 我非常希望您能在这个问题上帮助我。

A RandomAccessFile does not seem useful in this case. 在这种情况下, RandomAccessFile似乎没有用。 Using traditional stream-based I/O is best and certainly won't lead to out of memory errors unless you're doing it wrong. 最好使用传统的基于流的I / O,除非您做错了,否则肯定不会导致内存不足错误。 Here's really all the code you need (untested): 这实际上是您需要的所有代码(未经测试):

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) {}
}

If you really need a RandomAccessFile for some reason you can't tell us, the method is essentially the same. 如果由于某种原因您确实需要一个RandomAccessFile ,但您不能告诉我们,则方法本质上是相同的。 Find out how much data you actually read into your buffer using the result from RandomAccessFile.read(byte[], int, int) and use that number to limit how much you write back to the output file. 使用RandomAccessFile.read(byte[], int, int)的结果,找出实际读入缓冲区的数据量RandomAccessFile.read(byte[], int, int)并使用该数字来限制写回输出文件的量。

Edit 编辑

The above warrants some explanation. 上面有一些解释。 Here are the key parts: 以下是关键部分:

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

This initializes a byte array of 4 binary megabytes which will hold one chunk of the file at a time. 这将初始化一个4二进制兆字节的字节数组,该字节数组一次将保存一个文件块。

    for ( int len = 0; 

In a for loop, we start by declaring a value len that will record how many bytes we have read in. 在for循环中,我们首先声明一个值len ,该值将记录我们已读入的字节数。

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

Then we invoke read on the InputStream . 然后,我们在InputStream上调用read This will read bytes into the byte array until either the buffer is full, or there is no more data left to read (the end of file is reached). 这会将字节读取到字节数组中,直到缓冲区已满或没有更多数据可读取(到达文件末尾)为止。 The number of bytes actually read is returned by this method and assigned to len . 该方法返回实际读取的字节数,并将其分配给len If that value is -1, that means the stream is closed so we exit the loop. 如果该值为-1,则表示流已关闭,因此我们退出循环。

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

Then, for each chunk that we have read, we write it to the output stream. 然后,对于已读取的每个块,将其写入输出流。 buffer indicates we want to write from our byte array, the 0 indicates we want to start at the beginning of the array, and the len says how many bytes to write. buffer表示我们要从字节数组中写入, 0表示我们要从数组的开头开始, len表示要写入多少字节。 Remember, if our buffer wasn't filled then len will have been set accordingly and only part of the array will be written. 请记住,如果未填充缓冲区,则将相应地设置len ,并且仅写入数组的一部分。

I gave you the idiomatic version which can be more difficult to follow. 我给了你惯用的版本,可能很难理解。 Here's a more straightforward way of doing the same thing: 这是做同一件事的更直接的方法:

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
}

See 看到

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM