简体   繁体   English

StringBuilder追加导致内存不足

[英]StringBuilder append cause out of memory

i am getting out of memory error in asynctask which loop to stringbuilder . 我在asynctask中失去内存错误,循环到stringbuilder。 My target for using this to download image from server and store inside my sd card.My code as below : 我的目标是使用它从服务器下载图像并存储在我的SD卡内。我的代码如下:

HttpClient httpclient = new DefaultHttpClient();
        httpclient.getParams().setParameter(CoreProtocolPNames.PROTOCOL_VERSION, HttpVersion.HTTP_1_1);   
        HttpPost httppost = new HttpPost(severPath);        

        httppost.setEntity(params[0]);
        System.out.println("executing request " + httppost.getRequestLine());



            HttpResponse response = null;
            try {
                response = httpclient.execute(httppost);
            } catch (ClientProtocolException e6) {
                // TODO Auto-generated catch block
                e6.printStackTrace();
            } catch (IOException e6) {
                // TODO Auto-generated catch block
                e6.printStackTrace();
            }
            String output;
            System.out.println("Output from Server .... \n");

            BufferedReader br = null;
            try {
                br = new BufferedReader(
                        new InputStreamReader((response.getEntity().getContent())));
            } catch (IllegalStateException e5) {
                // TODO Auto-generated catch block
                e5.printStackTrace();
            } catch (IOException e5) {
                // TODO Auto-generated catch block
                e5.printStackTrace();
            }

             OutputStreamWriter outputStreamWriter = null;
            try {
                outputStreamWriter = new OutputStreamWriter(context.openFileOutput("LargeImages.txt", context.MODE_PRIVATE));
            } catch (FileNotFoundException e6) {
                // TODO Auto-generated catch block
                e6.printStackTrace();
            }
            int i = 0;


            StringBuilder builder = new StringBuilder();


            String Result = "";
                try {
                    for (String line = null; (line = br.readLine()) != null ; ) {
                                        builder.append(line.toString());

                    }
                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }




                    outputStreamWriter.close();

i am getting out of memory allocation error. 我没有内存分配错误。 please help. 请帮忙。 i try many method but also not getting the right. 我尝试了很多方法,但也没有做到正确。

There may be two problems. 可能有两个问题。 The first - the cycle for (String line = null; (line = br.readLine()) != null ; ) is not terminated properly. 第一个 - for (String line = null; (line = br.readLine()) != null ; )的循环未正确终止。 Try to find it out by opening a small file(eg with 10 lines total). 尝试通过打开一个小文件找到它(例如总共10行)。

The second - it's actually a memory insufficient case. 第二个 - 它实际上是一个记忆不足的情况。 Probably it's not the best idea to get image via strings as images may be very heavy and creating a plenty of Strings causes natural memory error. 可能通过字符串获取图像并不是最好的想法,因为图像可能非常沉重并且创建大量字符串会导致自然内存错误。 Try to find another approach. 尝试寻找另一种方法。

if you are downloading an image, then you should not use Reader/Writer/StringBuilder to store it's content. 如果您正在下载图像,则不应使用Reader/Writer/StringBuilder来存储它的内容。 Because the file is binary content will be scrambled because of the character encoding used by Reader/Writer classes. 因为文件是二进制内容,所以会因为Reader/Writer类使用的character encoding而被加扰。

Try using InputStream/OutputStream and store the content directly to sdcard without storing it in memory. 尝试使用InputStream/OutputStream并将内容直接存储到SD卡而不将其存储在内存中。

Try out the below code: 试试下面的代码:

InputStream in = response.getEntity().getContent();
OutputStream out = context.openFileOutput("LargeImages.txt", context.MODE_PRIVATE);
byte b[] = new byte[4096];
int i;
while ((i = in.read(b)) >= 0) {
    out.write(b, 0, i);
}

I don't see code that is actually writing to the output stream. 我没有看到实际写入输出流的代码。 Shouldn't there be a line before the close, that is like outputStreamWriter.print(builder) ? 关闭前不应该有一行,就像outputStreamWriter.print(builder)

About your question. 关于你的问题。 Instead of collecting the whole data in memory in a StringBuilder and than write it at once, you should write directly each line you get within your for-loop. 您应该直接在for-loop中直接写入每一行,而不是在StringBuilder中将整个数据收集到内存中,而不是一次写入。 You don't need the StringBuilder at all. 您根本不需要StringBuilder。 Here's a code snippet: 这是一段代码片段:

            try {
                for (String line = br.readLine(); line != null; line = br.readLine()) {
                    outputStreamWriter.append(line);
                }
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
                return;
            }

Three more remarks: 还有三点评论:

  • When you get an Exception you should also stop the action, eg return from your method. 当你得到一个异常时,你也应该停止动作,例如从你的方法返回。 Your code above would print the Stacktrace (which is definitely helpful) but would then continue, which would be not so helpful. 您上面的代码将打印Stacktrace(这肯定是有帮助的),但然后会继续,这将没有那么有用。 Just add return after each printstackTrace . 只需在每个printstackTrace之后添加return
  • There's still a chance that one line is too long for memory, but the risk is minimized. 一条线路的存储空间可能太长,但风险最小化。
  • Is the data you download binary image or text? 您下载的数据是二进制图像还是文本? You name it image but you download text. 您将其命名为图像但下载文本。 Please be aware that there's a difference between bytes and characters (encoded with character set) and stay within what you actually receive. 请注意,字节和字符(用字符集编码)之间存在差异,并保持在实际接收的范围内。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM