我试图在Android应用程序上阅读大小为base64
的大(~ 150MB)
文本文件。
该文件包含我需要解码的JSON字符串并将其转换为JSON对象,并在应用程序中使用它。问题是我在尝试读取此数据时遇到异常Out of Memory
。
该应用需要离线工作,因此我需要下载完整数据。
以下是代码:
String localPath = getApplicationContext().getFilesDir().getPath().toString() ;
String key = "dataFile.txt" ;
StringBuilder text = new StringBuilder();
File file=new File(localPath+"/"+ key);
byte fileContent[] = new byte[3000];
try ( FileInputStream fin = new FileInputStream(file)) {
while(fin.read(fileContent) >= 0) {
byte[] data = Base64.decode(fileContent, Base64.DEFAULT);
try {
text.append(new String(data, "UTF-8"));
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
}
obj = new JSONObject(text.toString());
}catch (Exception e){
e.printStackTrace();
}
我怎样才能读到这种文件?
答案 0 :(得分:2)
您正在尝试通过读取文件将整个文件读入text
对象,迭代它并将每行附加到text
。您可以从JSONObject
对象中创建text
,该对象仅在最后一步中对您的应用程序有用。
在这里,当您的代码到达行obj = new JSONObject(text.toString());
时,您已经填充了几乎与输入文件大小相当的堆,因为这个完整的文件以{{1}的形式存在于内存中对象。然后,您可以制作此test
个对象的JSONObject
。
您可以采取以下措施来解决此问题:
text
以块的形式读取文件(可选)。使用BufferedReader
可能有点慢,有一个缓冲区很好。read()
或text
批次的1000
对象中。10000
中准备JSONObject
并将其附加到text
。obj
对象,然后重复整个过程。通过执行此操作,您只读取内存中的一小部分文件,并且text
对象充当缓冲区,仅消耗少量内存。
以下是示例代码段:
text
答案 1 :(得分:2)
您唯一的选择是使用JSON streaming
并对您感兴趣的事件做出反应。
import org.codehaus.jackson.*;
.....
JsonParser parser = new JsonFactory().createJsonParser( yourFileInputStream );
parser.configure( Feature.ALLOW_BACKSLASH_ESCAPING_ANY_CHARACTER, true );
parser.configure( Feature.ALLOW_SINGLE_QUOTES, true );
// add more features
for( JsonToken token = parser.nextToken(); null != token; token = parser.nextToken() ){
switch( token ){
case FIELD_NAME:
doStuffWithName();
break;
case START_OBJECT:
doObjectStart();
break;
case END_OBJECT:
processObject();
break;
// other events
}
}
我在4.0设备上使用了上述代码,并使用了10 MB的JSON文件。
PS。您需要先解码原始Base64文件。不确定您是否可以在java.io.Stream
内动态执行此操作。在最坏的情况下,将Base64文件解压缩到plain-json中,然后使用上面的JSON流代码