简体   繁体   中英

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) Read it with RandomAccessFile (to avoid OutOfMemory error)
  • B) Read it by pieces of 4Mb (buffer)
  • C) Write each this 4Mb piece to file B.dat
  • D) So to make file B.dat as a copy of file 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 :(

For example... I have media file. Its length is 15.8Mb so I can get only 15.8Mb/4Mb=3 whole pieces. 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)...

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. Using traditional stream-based I/O is best and certainly won't lead to out of memory errors unless you're doing it wrong. 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. 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.

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.

    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.

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

Then we invoke read on the InputStream . 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 . If that value is -1, that means the stream is closed so we exit the loop.

) {
   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. Remember, if our buffer wasn't filled then len will have been set accordingly and only part of the array will be written.

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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