3

我正在尝试将大流(4mb)转换为字符串,我最终将其转换为 JSON 数组。

当流大小很小(以 KB 为单位)时,一切正常,当它开始处理 4mb 流时,它会耗尽内存

下面是我用来将流转换为字符串的方法,我几乎尝试了所有方法,我怀疑问题出在 while 循环上。有人可以帮忙吗?

  public String convertStreamToString(InputStream is)
            throws IOException {

        if (is != null) {
            Writer writer = new StringWriter();

            char[] buffer = new char[1024];
            try
            {
                Reader reader = new BufferedReader(
                        new InputStreamReader(is, "UTF-8"));
                int n;
                while ((n = reader.read(buffer)) != -1) 
                {
                    writer.write(buffer, 0, n);
                }
            }
            finally 
            {
                is.close();
            }
            return writer.toString();
        } else {       
            return "";
        }
    }

更新:好的,这是我目前到达的地方,我在正确的轨道上吗?我想我已经接近了..不确定我还能关闭或刷新什么来恢复记忆..

public String convertStreamToString(InputStream is)
        throws IOException {

    String encoding = "UTF-8";
    int maxlines = 2000;
    StringWriter sWriter = new StringWriter(7168);
    BufferedWriter writer = new BufferedWriter(sWriter);
    BufferedReader reader = null;
    if (is == null) {
        return "";
    } else {     


        try {
            int count = 0;
            reader = new BufferedReader(new InputStreamReader(is, encoding));
            for (String line; (line = reader.readLine()) != null;) {
                if (count++ % maxlines == 0) {
                    sWriter.close();
                    // not sure what else to close or flush here to regain memory
                    //Log.v("Max Lines Reached", "Max Lines Reached");;
                }

                writer.write(line);


            }
            Log.v("Finished Loop", "Looping over");


    } finally {
        is.close();
        writer.close();

    }
        return writer.toString();
    }
}
4

1 回答 1

3

StringWriter写入到StringBuffer内部。AStringBuffer基本上是一个char数组的包装器。那阵有一定的容量。当该容量不足时,StringBuffer将分配一个新的更大的char数组并复制前一个的内容。最后调用toString()StringWriter,它将再次将数组的内容复制charchar结果字符串的数组中。

如果您有任何方法事先知道所需的容量是多少,您应该使用 StringWriter 的构造函数来设置初始容量。这将避免不必要地复制数组以增加缓冲区。

然而,这并不能避免发生在toString(). 如果您正在处理可能很大的流,您可能需要重新考虑是否真的需要该输入流作为String. 直接使用足够大的char数组将避免所有复制,并会大大减少内存使用。

最终的解决方案是在所有输入进入之前对输入进行一些处理,以便可以丢弃已处理的字符。这样,您只需要在内存中保存与处理步骤所需的一样多的内存。

于 2012-12-22T18:21:39.543 回答