读取大体积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
相关产品推荐
相关产品推荐

