Base64-encode a file and compress it

dmurali picture dmurali · Mar 13, 2012 · Viewed 21.4k times · Source

My goal is to encode a file and zip it in a folder in java. I have to use the Apache's Commons-codec library. I am able to encode and zip it and it works fine but when i decode it back to its original form, it looks like the file has not completely been encoded. Looks like a few parts are missing. Can anybody tell me why this happens?

I am also attaching the part of my code for your reference so that you can guide me accordingly.

private void zip() {
    int BUFFER_SIZE = 4096;
    byte[] buffer = new byte[BUFFER_SIZE];

    try {
        // Create the ZIP file
        String outFilename = "H:\\OUTPUT.zip";
        ZipOutputStream out = new ZipOutputStream(new FileOutputStream(
                outFilename));

        // Compress the files
        for (int i : list.getSelectedIndices()) {
            System.out.println(vector.elementAt(i));
            FileInputStream in = new FileInputStream(vector.elementAt(i));
            File f = vector.elementAt(i);

            // Add ZIP entry to output stream.
            out.putNextEntry(new ZipEntry(f.getName()));

            // Transfer bytes from the file to the ZIP file
            int len;

            while ((len = in.read(buffer)) > 0) {
                buffer = org.apache.commons.codec.binary.Base64
                        .encodeBase64(buffer);
                out.write(buffer, 0, len);

            }

            // Complete the entry
            out.closeEntry();
            in.close();

        }

        // Complete the ZIP file
        out.close();
    } catch (IOException e) {
        System.out.println("caught exception");
        e.printStackTrace();
    }
}

Answer

DRCB picture DRCB · Mar 13, 2012

BASE64 encoded data are usually longer than source, however you are using the length of the source data to write encoded to output stream.

You have use size of the generated array instead of your variable len.

Second notice - do not redefine buffer each time you encode a byte. Just write result into output.

 while ((len = in.read(buffer)) > 0)  {                         
     byte [] enc = Base64.encodeBase64(Arrays.copyOf(buffer, len));
     out.write(enc, 0, enc.length);
 }

UPDATE: Use Arrays.copyOf(...) to set length of the input buffer for encoding.