You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

读取大体积Assets文件时抛出OutOfMemoryException异常

解决Assets文件读取OutOfMemoryException问题

嘿,这个坑我之前踩过!一次性把22MB的文件全塞进字节数组里,在Android设备上很容易触发内存溢出——毕竟Android给单个应用分配的内存有限,一下子占这么大内存,系统可不干。

问题根源

你当前的代码直接通过is.available()获取文件大小,然后创建一个和文件一样大的byte[],这会瞬间占用22MB的内存空间。如果你的应用当时还有其他内存占用(比如界面、图片等),很容易就超过内存阈值,抛出OOM。而且is.available()返回的其实只是输入流当前可读取的字节数,并不一定是文件的真实总大小,用它来创建数组本身就有风险。

优化方案:逐块读取+缓冲流

推荐用BufferedReader配合InputStreamReader逐行读取,用StringBuilder拼接内容。这样每次只加载一小段数据到内存,内存占用会低很多:

try {
    InputStream is = MainActivity.this.getAssets().open("file.json");
    // 用BufferedReader做缓冲,默认缓冲区大小是8KB,也可以自己指定
    BufferedReader reader = new BufferedReader(new InputStreamReader(is, "UTF-8"));
    StringBuilder contentBuilder = new StringBuilder();
    String line;
    
    // 逐行读取并拼接
    while ((line = reader.readLine()) != null) {
        contentBuilder.append(line);
    }
    
    // 记得关闭流,也可以用try-with-resources语法自动关闭
    reader.close();
    is.close();
    data = contentBuilder.toString();
} catch (Exception e) {
    // 别吞异常!至少打印栈信息方便调试
    e.printStackTrace();
}

更高效的方式:用AssetFileDescriptor

如果文件特别大,还可以直接通过AssetFileDescriptor获取文件描述符,绕开AssetInputStream的额外开销:

try {
    AssetFileDescriptor afd = MainActivity.this.getAssets().openFd("file.json");
    BufferedReader reader = new BufferedReader(new FileReader(afd.getFileDescriptor()));
    StringBuilder contentBuilder = new StringBuilder();
    String line;
    
    while ((line = reader.readLine()) != null) {
        contentBuilder.append(line);
    }
    
    reader.close();
    afd.close();
    data = contentBuilder.toString();
} catch (Exception e) {
    e.printStackTrace();
}

进阶建议:流式JSON解析

如果你的目的是解析这个大JSON文件,其实没必要把整个文件转成String再解析。可以用Gson的JsonReader或者Jackson的流式API,边读边解析,内存占用会降到最低——比如只提取你需要的字段,不用加载整个JSON结构到内存里。

内容的提问来源于stack exchange,提问作者Arab Ware

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.27 17:52:42