1

I'm facing an Out of Memory Exception while converting a 1.8MB image to bytes and then encrypt, finally converting into a string (length printed in log is 1652328). And then, I'm appending this string to some XML format to post, where the real problem arises. While appending some tags to this pictureString using StringBuffer or StringBuilder or adding to a string Out of Memory exception is occuring. How can I resolve this issue?

For small images this issue is not replicating.

The below piece of code converts a picture at path path to String.

fis = new FileInputStream(path);
buffer = new byte[fis.available()];
try {
    fis.read(buffer, 0, buffer.length);
    String byteString = 
        com.mobile.android.components.Base64.encodeBytes(buffer);
    return byteString;
} catch (IOException ex) {

}

The above byteString is appended to xml post as follows.

StringBuilder pictureName = new StringBuilder();
pictureName.append(byteString ); //here array out of bound at StringBuilder.extendBuffer
..........
appending continues

UPDATED

In the above appending, encoded byteStream is encrypted using cypher AES and then appended to StringBuilder.

palacsint
  • 28,416
  • 10
  • 82
  • 109
sha
  • 1,410
  • 2
  • 18
  • 37
  • Are you converting it into a Base64 string? – Che Jami Sep 26 '11 at 15:26
  • 1
    Converting an image into text, XML even, isn't the Right Thing To Do. – Philipp Reichart Sep 26 '11 at 15:30
  • @CheJami ,Yes i'm using Base64Encoding to retrive String – sha Sep 27 '11 at 05:21
  • @PhilippReichart I'm unable to figure out any other solution.Please suggest. – sha Sep 27 '11 at 05:22
  • Is the end receiving the XML under your control? If so, you could try to use a different approach like a regular "file upload" servlet/action/etc. or a RESTful web service (e.g. using [Jersey](http://jersey.java.net/)) to upload the image -- each of those can handle binary data natively, no conversion to string needed. – Philipp Reichart Sep 27 '11 at 06:33
  • If you don't control the receiving end, you'll need to post the code where you actually do the POST. I bet there's some way to stream the POST data from disk, so you could go via temp files to keep the memory consumption low. – Philipp Reichart Sep 27 '11 at 06:34
  • Server End is not in our control.Will try the suggested method.Thanks – sha Sep 27 '11 at 07:16
  • If i save the string in disk also,firstly i have to save the string or while posting i have to convert into the string inorder to attach to the COmplete post Data.So the issue still exist. – sha Sep 27 '11 at 12:15

2 Answers2

1

Call bitmap.recycle(); as soon as you have converted the bitmap to a byte array. This will free the native object associated with this bitmap, and clear the reference to the pixel data.

Update

Its obvious that the memory chunk read from the filestream is too large to handle. Avoid reading the whole file at once. Do it piece by piece. Append the string to the xml without using an intermediate string object.

Update 2

You could do something like this to avoid loading the whole xml file while sending it to server.

// Allow Inputs & Outputs
connection.setDoInput(true);
connection.setDoOutput(true);
connection.setUseCaches(false);

// Enable POST method
connection.setRequestMethod("POST");

outputStream = new DataOutputStream( connection.getOutputStream() );
// Read file
bytesRead = fileInputStream.read(buffer, 0, bufferSize);

while (bytesRead > 0)
{
    outputStream.write(buffer, 0, bufferSize);
    bytesAvailable = fileInputStream.available();
    bufferSize = Math.min(bytesAvailable, maxBufferSize);
    bytesRead = fileInputStream.read(buffer, 0, bufferSize);
}

Then write the boundry characters, flush and close the streams.

Ron
  • 24,175
  • 8
  • 56
  • 97
  • I'm not using the bitmap , rather using fileconnection to get bytes and then to String. – sha Sep 27 '11 at 05:25
  • Thanks.I'll try the method and post back on the result – sha Sep 27 '11 at 07:21
  • @userServen7s Same prob still exist.I used to have 2 problems for Out of Memory, One with Bitmap and another with the String(this Thread).I resolved Bimtap issue from http://stackoverflow.com/questions/477572/android-strange-out-of-memory-issue but this String problem still exist.If i give initial capacity for StringBuffer the same problem reproduced. – sha Sep 27 '11 at 12:10
  • then dont hold the xml in memory. create a file and write the sub strings to it using out streams. when finished, read back and send that file content. – Ron Sep 27 '11 at 13:03
0

Thanks everyone for the support.

I finally optimized my code to a max extent using file operations.

For encoding I used Base64.encodeFileToFile(picturePath, encodedPicturePath); I saved the encoded image in a file. And then for encryption,I used CypherOutPutStream where a FileOutputStream is passed in constructor.So Encryption is also done using file. The final step is while using HttpPost,I used to send the total encrypted data as a StringEntity which is final Hurdle for OutOfMemeoryException.I changed the StringEntity to FileEntity.This reduced the heap consumption of my application and thus improved the overall performance and upload capacity.

Note: Dont Encrypt the encoded image in chunks which will change the overall encoded data.Do it inn a single piece.

Failures: Before i used files for Encoding ,I chunked the whole picture and encoded to a file.But,If i decode the encoded file,I failed to get the original picture.

Regards,Sha

sha
  • 1,410
  • 2
  • 18
  • 37