14

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 ?

Labe
  • 1,262
  • 2
  • 20
  • 30

2 Answers2

18

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();
Dalija Prasnikar
  • 27,212
  • 44
  • 82
  • 159
  • 1
    Thank you for your answer! I will look into multipart (with retrofit) and else... – Labe Jan 08 '15 at 15:13
  • how to get original file from this base64 encoded string? – Vishal Senjaliya Dec 11 '18 at 10:26
  • @AndroCoderHelper [Base64InputStream](https://developer.android.com/reference/android/util/Base64InputStream) – Dalija Prasnikar Dec 11 '18 at 10:28
  • Getting OutOfMemorry exception when trying large(100mb) file. Any solution for this? – Vishal Senjaliya Dec 19 '18 at 12:35
  • @AndroCoderHelper depends on your requirements. In general, like I mentioned in my answer, avoid keeping data in memory and use temporary files instead. Instead of using ByteArrayOutputStream use file for output. Base64OutputStream or Base64InputStream coding/decoding through buffer will not give you problems. Your actual input/output storage is where it fails. – Dalija Prasnikar Dec 19 '18 at 13:42
  • `byte[] buffer = new byte[8192];` the length of the byte array is fixed? – Shalan93 Mar 31 '19 at 09:50
  • 1
    @MohamedFotouhShalan Yes, it is fixed. You can use different buffer size. With larger buffer processing will be slightly faster, but it will use more memory. 4-64Kb buffers are most commonly used. – Dalija Prasnikar Mar 31 '19 at 09:59
0
// Converting File to Base64.encode String type using Method
public String getStringFile(File f) {
    InputStream inputStream = null;
    String encodedFile = "", lastVal;
    try {
        inputStream = new FileInputStream(f.getAbsolutePath());

        byte[] buffer = new byte[10240]; //specify the size to allow
        int bytesRead;
        ByteArrayOutputStream output = new ByteArrayOutputStream();
        Base64OutputStream output64 = new Base64OutputStream(output, Base64.DEFAULT);

        while ((bytesRead = inputStream.read(buffer)) != -1) {
            output64.write(buffer, 0, bytesRead);
        }


        output64.close();


        encodedFile = output.toString();

    } catch (FileNotFoundException e1) {
        e1.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }
    lastVal = encodedFile;
    return lastVal;
}
Kiran S
  • 78
  • 1
  • 10
Edwinfad
  • 515
  • 6
  • 14