Search code examples
androidfilebase64android-file

Convert a file (<100Mo) in Base64 on Android


I am trying to convert a file from the sdcard to Base64 but it seems the file is too big and i get an OutOfMemoryError.

Here is my code :

InputStream inputStream = null;//You can get an inputStream using any IO API
inputStream = new FileInputStream(file.getAbsolutePath());
byte[] bytes;
byte[] buffer = new byte[8192];
int bytesRead;
ByteArrayOutputStream output = new ByteArrayOutputStream();
try {
    while ((bytesRead = inputStream.read(buffer)) != -1) {
        output.write(buffer, 0, bytesRead);
    }
} catch (IOException e) {
    e.printStackTrace();
}
bytes = output.toByteArray();
attachedFile = Base64.encodeToString(bytes, Base64.DEFAULT);

Is there a way to go around the OutOfMemoryError while filing the String attachedFile ?


Solution

  • Base64 encoding takes 3 input bytes and converts them to 4 bytes. So if you have 100 Mb file that will end up to be 133 Mb in Base64. When you convert it to Java string (UTF-16) it size will be doubled. Not to mention that during conversion process at some point you will hold multiple copies in memory. No matter how you turn this it is hardly going to work.

    This is slightly more optimized code that uses Base64OutputStream and will need less memory than your code, but I would not hold my breath. My advice would be to improve that code further by skipping conversion to string, and using temporary file stream as output instead of ByteArrayOutputStream.

    InputStream inputStream = null;//You can get an inputStream using any IO API
    inputStream = new FileInputStream(file.getAbsolutePath());
    byte[] buffer = new byte[8192];
    int bytesRead;
    ByteArrayOutputStream output = new ByteArrayOutputStream();
    Base64OutputStream output64 = new Base64OutputStream(output, Base64.DEFAULT);
    try {
        while ((bytesRead = inputStream.read(buffer)) != -1) {
            output64.write(buffer, 0, bytesRead);
        }
    } catch (IOException e) {
        e.printStackTrace();
    }
    output64.close();
    
    attachedFile = output.toString();