Java/Android:Java.lang.OutOfMemoryError在构建JSON对象时出错
我正在从一个公共数据库URI导入JSON数据,行数达到445454行。使用下面的代码,我正在构建整个数据的JSON对象Java/Android:Java.lang.OutOfMemoryError在构建JSON对象时出错,java,android,json,webrequest,Java,Android,Json,Webrequest,我正在从一个公共数据库URI导入JSON数据,行数达到445454行。使用下面的代码,我正在构建整个数据的JSON对象 HttpGet get = new HttpGet(uri); HttpClient client = new DefaultHttpClient(); HttpResponse response = client.execute(get); BufferedReader reader = new BufferedReader(new InputStre
HttpGet get = new HttpGet(uri);
HttpClient client = new DefaultHttpClient();
HttpResponse response = client.execute(get);
BufferedReader reader = new BufferedReader(new InputStreamReader(response.getEntity().getContent(), "UTF-8"));
StringBuilder builder=new StringBuilder();
for(String line=null;(line = reader.readLine()) != null;){
builder.append(line).append("\n");
}
JSONTokener jsonTokener=new JSONTokener(builder.toString());
JSONObject finalJson=new JSONObject(jsonTokener);
JSONArray data=finalJson.getJSONArray("data");
由于数据太大,我得到了
03-21 03:41:49.714:E/AndroidRuntime(666):原因是:java.lang.OutOfMemoryError
将错误源指向buildr.append(line).append(“\n”)
。我是否可以处理大型数据集而不出现内存分配问题?如果可能,只请求部分数据-这也减少了网络io的时间,从而节省了电池
否则,您可以尝试不将传入的数据保存在内存中,而是将其“流”到sd卡上。当它存储在那里时,您可以对其进行迭代。这很可能意味着使用您自己的JSON标记器,它不构建完整的树,但能够(像SAX解析器一样)一次只查看对象树的一部分
您可以看看,它有一个流模式,这可能是适用的。JSON是巨大的
您肯定需要使用流式JSON解析器。Android有两种:GSON和Jackson
GSON流媒体的解释如下:
我喜欢GSON如何解释您遇到的问题:
大多数应用程序应该只使用对象模型API。JSON流在以下几种情况下非常有用:
当无法或不希望将整个对象模型加载到内存中时。这在内存有限的移动平台上最为相关
Jackson流媒体记录在:流媒体拉式解析器就是一种方式。我建议使用GSON,因为它的内存占用空间很小(仅拉动解析大约为16K,jackson要大得多) 您的代码有问题,因为您分配了:
- 用于保存来自服务的所有字符串数据的缓冲区
- 所有JSON DOM对象
我的做法有点不同,我的JSON代码正在等待状态,状态即将结束。因此,我修改了代码以更早地返回
// try to get formattedAddress without reading the entire JSON
String formattedAddress;
while ((read = in.read(buff)) != -1) {
jsonResults.append(buff, 0, read);
formattedAddress = ((String) ((JSONObject) new JSONObject(
jsonResults.toString()).getJSONArray("results").get(0))
.get("formatted_address"));
if (formattedAddress != null) {
Log.i("Taxeeta", "Saved memory, returned early from json") ;
return formattedAddress;
}
}
JSONObject statusObj = new JSONObject(jsonResults.toString());
String status = (String) (statusObj.optString("status"));
if (status.toLowerCase().equals("ok")) {
formattedAddress = ((String) ((JSONObject) new JSONObject(
jsonResults.toString()).getJSONArray("results").get(0))
.get("formatted_address"));
if (formattedAddress != null) {
Log.w("Taxeeta", "Did not saved memory, returned late from json") ;
return formattedAddress;
}
}
阅读其中的一部分而不是全部?我喜欢GSON。所以你是说,我不应该使用
BufferedReader
和StringBuilder
而应该使用JSONReader
和List
来克服内存问题?正确。JSONReader将接收您的inputStream,以便在代码中同时替换BufferedReader和StringBuilder。注意,Message是一个示例类。看看这个JSON,您可能想用自己的policResponse类来代替它。由于JSON不像示例中那样只是一个大数组,因此必须首先导航到包含警方响应的数组,然后才能开始遍历该数组。