Question

I am trying to read a 2mb file into a memory and then send that file to web server. But I am getting out of memory exception.

         FileConnection fileConn = (FileConnection)Connector.open("file:///" + pictureURI.getString(), Connector.READ);
     InputStream fis = fileConn.openInputStream();
     long overallSize = fileConn.fileSize();

     int chunkSize = 2048;
     int length = 0;
     while (length < overallSize)
     {

        byte[] data = new byte[chunkSize];
        int readAmount = fis.read(data, 0, chunkSize);
        byte[] newImageData = new byte[rawImage.length + chunkSize];
        System.arraycopy(rawImage, 0, newImageData, 0, length);
        System.arraycopy(data, 0, newImageData, length, readAmount);
        rawImage = newImageData;
        length += readAmount;

     }
       fis.close();
        fileConn.close(); 

500kb files are uploading. What could be the reason? Please shed a light on this.

I tried this also in loop but no use, System.gc();

[EDIT] https://stackoverflow.com/users/45668/malcolm has put me on right track. Now I struck here

  this.progress = progress;

  HttpConnection conn = null;
  OutputStream os = null;
  InputStream s = null;
  StringBuffer responseString = new StringBuffer();

  try
  {
     System.out.println(System.getProperty("HTTPClient.dontChunkRequests"));
     conn = (HttpConnection)Connector.open(url);
     //conn.setRequestProperty("User-Agent", "Profile/MIDP-2.1 Configuration/CLDC-1.1");
     conn.setRequestMethod(HttpConnection.POST);

     // The messages
     conn.setRequestProperty("Content-Type", "multipart/form-data; boundary=---------------------------4664151417711");
     conn.setRequestProperty("Content-Length", "355");

     os = conn.openOutputStream();

     System.out.println("file name at upload " + fileName);
     String message1 = "";
     message1 += "-----------------------------4664151417711\r\n";
     message1 += "Content-Disposition: form-data; name=\"file\"; filename=\"" + fileName + "\"\r\n";
     message1 += "Content-Type: image/gif\r\n";
     message1 += "\r\n";

     os.write(message1.getBytes());

     System.gc();

     // Send the image
     int index = 0;
     int size = 2048;
     double progdouble;
     do
     {
        progdouble = ((double)index) / ((double)rawImage.length) * 100;
        progress.setValue((int)progdouble);

        if((index+size) > rawImage.length)
        {
           size = rawImage.length - index;
        }
        os.write(rawImage, index, size);
        index += size;

        System.gc();
     } while(index < rawImage.length);

     String message2 = "\r\n-----------------------------4664151417711\r\n";
     message2 += "Content-Disposition: form-data; name=\"number\"\r\n\r\n";
     message2 += this.user_phone_number;         

     os.write(message2.getBytes());

     String message3 = "\r\n-----------------------------4664151417711\r\n";
     message3 += "Content-Disposition: form-data; name=\"uuid\"\r\n\r\n";
     message3 += this.user_uuid;         

     os.write(message3.getBytes());

     String message4 = "\r\n-----------------------------4664151417711--\r\n";  

     os.write(message4.getBytes());


     os.flush();
     os.close();

     // Read

     s = conn.openInputStream();
     int ch, i = 0, maxSize = 16384;
     while(((ch = s.read())!= -1 ) & (i++ < maxSize)) 
     {
        responseString.append((char) ch);
     }

     conn.close();
     System.out.println("response =>"+responseString.toString());



     return responseString.toString();
  }
  catch (IOException ioe)
  {
     return ioe.toString();
  }

Now its failing here..

[EDIT2]

// algorithm that will read 1024 bytes at a time 
        byte b[] = new byte[chunkSize];
        for (int i = 0; i < overallSize; i += chunkSize) { 

            if ((i + chunkSize) < overallSize) {
                fis.read(b, 0, chunkSize);
            } else {
                int left = (int)overallSize - i;
                fis.read(b, 0, left);
            }

            // writing into the output stream - ( these lines will cause the "memory leak", without these, it will not happen)
            os.write(b);
            System.gc(); 

            progdouble = ((double)i) / ((double)overallSize) * 100;
            progress.setValue((int)progdouble); 
        }
        os.flush();

Thanks in advance.

Was it helpful?

Solution

You allocate a lot of new arrays along the way, which is totally unnecessary. Each new byte[] line allocates a new array.

You should read into one large array, and you should allocate it once, before the loop. You can easily do this since you know the exact size of the file. The code will look something like this:

FileConnection fileConn;
InputStream is;

try {
    fileConn = (FileConnection) Connector.open("file:///" + pictureURI.getString(), Connector.READ);
    is = fileConn.openInputStream();

    long overallSize = fileConn.fileSize();
    if (overallSize > Integer.MAX_VALUE) throw new IllegalArgumentException("File is too large);
    byte[] imageData = new byte[(int) overallSize];
    int chunkSize = 2048;
    int bytesReadTotal = 0;
    while (bytesRead < overallSize) {
        int bytesRead = is.read(imageData, bytesReadTotal, Math.min(imageData.length - bytesReadTotal, chunkSize));
        if (bytesRead == -1) break;
        bytesReadTotal += bytesRead;
    }
} finally {
    if (is != null) is.close();
    if (fileConn != null) fileConn.close();
}

OTHER TIPS

Your mobile (Nokia x2-01 specs) is limited to 2Mb of heap space for the whole app. Design your app according to these limitations. 2Mb bytearray in memory at once - no way.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top