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
- InputStream.read(byte[])
- OutputStream.write(byte[], int, int)
精彩评论