Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Split and join back a binary file in java

Tags:

java

file-io

I am trying to divide a binary file (like video/audio/image) into chunks of 100kb each and then join those chunks back to get back the original file. My code seems to be working, in the sense that it divides the file and joins the chunks, the file I get back is of the same size as original. However, the problem is that the contents get truncated - that is, if it's a video file it stops after 2 seconds, if it is image file then only the upper part looks correct.

Here is the code I am using (I can post the entire code if you like):

For dividing:

File ifile = new File(fname); 
FileInputStream fis;
String newName;
FileOutputStream chunk;
int fileSize = (int) ifile.length();
int nChunks = 0, read = 0, readLength = Chunk_Size;
byte[] byteChunk;
try {
    fis = new FileInputStream(ifile);
    StupidTest.size = (int)ifile.length();
    while (fileSize > 0) {
        if (fileSize <= Chunk_Size) {
            readLength = fileSize;
        }
        byteChunk = new byte[readLength];
        read = fis.read(byteChunk, 0, readLength);
        fileSize -= read;
        assert(read==byteChunk.length);
        nChunks++;
        newName = fname + ".part" + Integer.toString(nChunks - 1);
        chunk = new FileOutputStream(new File(newName));
        chunk.write(byteChunk);
        chunk.flush();
        chunk.close();
        byteChunk = null;
        chunk = null;
    }
    fis.close();
    fis = null;

And for joining file, I put the names of all chunks in a List, then sort it by name and then run the following code:

File ofile = new File(fname);
FileOutputStream fos;
FileInputStream fis;
byte[] fileBytes;
int bytesRead = 0;
try {
    fos = new FileOutputStream(ofile,true);             
    for (File file : files) {
        fis = new FileInputStream(file);
        fileBytes = new byte[(int) file.length()];
        bytesRead = fis.read(fileBytes, 0,(int)  file.length());
        assert(bytesRead == fileBytes.length);
        assert(bytesRead == (int) file.length());
        fos.write(fileBytes);
        fos.flush();
        fileBytes = null;
        fis.close();
        fis = null;
    }
    fos.close();
    fos = null;
like image 761
Vinay Pandey Avatar asked Dec 13 '10 18:12

Vinay Pandey


1 Answers

I can spot only 2 potential mistakes in the code:

int fileSize = (int) ifile.length();

The above fails when the file is over 2GB since an int cannot hold more.

newName = fname + ".part" + Integer.toString(nChunks - 1);

A filename which is constructed like that should be sorted on a very specific manner. When using default string sorting, name.part10 will namely come before name.part2. You'd like to supply a custom Comparator which extracts and parses the part number as an int and then compare by that instead.

like image 74
BalusC Avatar answered Sep 20 '22 07:09

BalusC