InputStream和OutOfMemory错误

时间:2016-07-22 14:43:30

标签: java android json out-of-memory inputstream

public String loadJSONFromAsset(String path) {
    String json = null;
    try {
        InputStream is = this.getAssets().open(path);
        int size = is.available();
        Log.d("Size: ", "" +size);
        byte[] buffer = new byte[size];
        is.read(buffer);
        is.close();
        json = new String(buffer, "UTF-8");
    } catch (IOException ex) {
        ex.printStackTrace();
    }
    return json;
}

这是将文件转换为JSON数据文件的代码。它按字面意思工作,它创建JSON文件但“is”的大小是appr。 8MB

D/Size:: 7827533

和OutOfMemory错误发生在大多数设备上,例如

java.lang.OutOfMemoryError
at java.lang.String.<init>(String.java:255)
at java.lang.String.<init>(String.java:228)
at com.example.fkn.projecttr.List.loadJSONFromAsset(List.java:255)

我该如何处理?如何编码更有效?它没有运行时间的问题,但它消耗的设备内存太大。因此,当设备存储器没有更多容量时,程序崩溃。

2 个答案:

答案 0 :(得分:1)

我注意到了这一点:

    int size = is.available();

并认为这有点奇怪。所以我去看了the JavaDoc for InputStream.available,这就是它所说的:

  

请注意,虽然InputStream的某些实现将返回流中的总字节数,但许多实现不会。使用此方法的返回值来分配用于保存此流中所有数据的缓冲区是绝对正确的。

所以你有两个条件之一:

  1. 您的文件大小实际为8MB。

    如果你真的拥有这么多JSON,你需要重新思考那里的内容以及你正在使用它的内容。我没有看到很多开发人员使用的一个选项是JsonReader,它允许您解析JSON而不首先将整个流加载到内存中。

  2. 您的文件大小远小于8MB

    请以不同方式阅读该文件,请参阅How do I create a Java string from the contents of a file?

答案 1 :(得分:0)

保持字节压缩,GZipOutputStream在ByteArrayOutputStream(或gzip压缩资产)上。

然后总是使用GZipInputStream处理输出,解析或其他任何内容。

这至少可以安全20倍(压缩10次,开销减少约3倍)。

对于侵入性较小的更改(以及更多的内存消耗):现在有一个8 MB的字节数组和一个16 MB的字符串。字符串可以立即解析为DOM,所以JSON。丢弃空格,并将相等的String值映射到一个String实例(例如,通过Map<String, String> idmap)。这取决于数据中是否有很多重复。