Android 中 String、StringBuffer 和 StringBuilder 的内存不足异常

发布于 2024-12-06 16:59:54 字数 979 浏览 1 评论 0原文

我在将 1.8MB 图像转换为字节然后加密,最后转换为字符串(日志中打印的长度为 1652328)时遇到内存不足异常。然后,我将此字符串附加到某种 XML 格式中以进行发布,这正是真正的问题出现的地方。使用 StringBufferStringBuilder 向此 pictureString 附加一些标签或添加到字符串时,发生内存不足异常。我该如何解决这个问题?

对于小图像,此问题不会重现。

下面的代码将路径 path 处的图片转换为 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) {

}

上面的 byteString 被附加到 xml post 中,如下所示。

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

更新

在上面的附加中,编码的byteStream使用cypher AES加密,然后附加到StringBuilder

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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

鹿港巷口少年归 2024-12-13 16:59:54

将位图转换为字节数组后,立即调用 bitmap.recycle();。这将释放与该位图关联的本机对象,并清除对像素数据的引用。

更新

很明显,从文件流读取的内存块太大而无法处理。避免一次读取整个文件。一点一点地做。将字符串附加到 xml,而不使用中间字符串对象。

更新 2

您可以执行类似的操作,以避免在将其发送到服务器时加载整个 xml 文件。

// 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);
}

然后写入边界字符,刷新并关闭流。

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.

各自安好 2024-12-13 16:59:54

感谢大家的支持。

我终于利用文件操作最大限度地优化了我的代码。

对于编码,我使用Base64.encodeFileToFile(picturePath,encodedPicturePath);
我将编码后的图像保存在文件中。
然后对于加密,我使用CypherOutPutStream,其中 FileOutputStream 在构造函数中传递。因此加密也是使用文件完成的。
最后一步是在使用 HttpPost 时,我曾经将全部加密数据作为 StringEntity 发送,这是 OutOfMemeoryException 的最终障碍。我将 StringEntity 更改为 FileEntity< /code>。这减少了我的应用程序的堆消耗,从而提高了整体性能和上传能力。

笔记:
不要以块的形式对编码图像进行加密,这会改变整个编码数据。请在单个块中进行加密。

失败:
在我使用文件进行编码之前,我将整个图片分块并编码到一个文件中。但是,如果我解码编码文件,我无法获得原始图片。

问候,沙

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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文