解析大型 JSON 响应时出现 OutOfMemoryException

发布于 2024-11-09 15:26:29 字数 6716 浏览 0 评论 0原文

我正在做一个项目,我需要通过 HttpClient 从 URL 解析 JSON。我的代码适用于具有少量数据的 JSON 对象响应。但是当我使用相同的代码获得大量数据(超过 3MB)的响应时,我遇到了问题。

这是我的代码:

JSONfunctions.java(json 解析函数)

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
//import java.util.HashMap;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
//import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
//import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import android.util.Log;
import android.widget.Toast;

@SuppressWarnings("unused")
public class JSONfunctions {

    public static JSONObject getJSONfromURL(String url){
        InputStream is = null;
        String result = "";
        JSONObject jArray = null;

        //http post
        try{
                HttpClient httpclient = new DefaultHttpClient();
                HttpPost httppost = new HttpPost(url);
                HttpResponse response = httpclient.execute(httppost);
                HttpEntity entity = response.getEntity();
                is = entity.getContent();

        }catch(Exception e){
                Log.e("log_tag", "Error in http connection "+e.toString());
        }

        //convert response to string
        try{
                BufferedReader reader = new BufferedReader(new InputStreamReader(is,"iso-8859-1"),8);
                StringBuilder sb = new StringBuilder();
                String line = null;
                while ((line = reader.readLine()) != null) {
                        sb.append(line + "\n");
                }
                is.close();
                result=sb.toString();

            //    Toast.makeText(getBaseContext, result, Toast.LENGTH_LONG).

        }catch(Exception e){
                Log.e("log_tag", "Error converting result "+e.toString());
        }

        try{

            jArray = new JSONObject(result);            
        }catch(JSONException e){
                Log.e("log_tag", "Error parsing data "+e.toString());
        }

        return jArray;
    }
}

ListJson.java

import java.util.ArrayList;
import java.util.HashMap;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
//import org.w3c.dom.Document;
//import org.w3c.dom.Element;
//import org.w3c.dom.NodeList;



import android.app.ListActivity;
import android.content.Intent;
//import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ListAdapter;
import android.widget.ListView;
import android.widget.SimpleAdapter;
import android.widget.Toast;


public class ListJson extends ListActivity {
     public static JSONObject json;
     public static JSONArray data;
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.list1);

        ArrayList<HashMap<String, String>> mylist = new ArrayList<HashMap<String, String>>();
     //   String semail = "[email protected]";
      //  String spassword = "partha123";


      //  Toast.makeText(getApplicationContext(), JSONExample2.strEmail, Toast.LENGTH_LONG).show();
        //Toast.makeText(getApplicationContext(), JSONExample2.strPwd, Toast.LENGTH_LONG).show();

        //    

        json = JSONfunctions.getJSONfromURL("url here");      


            try{

            data = json.getJSONArray("server_list");


            for(int i=0;i<data.length();i++){                       
                HashMap<String, String> map = new HashMap<String, String>();    
                JSONObject e = data.getJSONObject(i);

                map.put("id", String.valueOf(i));
                map.put("name", "" + e.getString("ServUser"));
                map.put("email", "" + e.getString("ServURL"));
                mylist.add(map);
            }       
        }catch(JSONException e)        {
             Log.e("log_tag", "Error parsing data "+e.toString());
        }


//        try {
//          JSONObject newObject=json.getJSONObject("subscription");
//          JSONArray data1 = newObject.getJSONArray("cust_product");
//          
//          Toast.makeText(getApplicationContext(), data1.toString(), Toast.LENGTH_LONG).show();
//         
//          for(int i=0;i<data1.length();i++){                      
//                  HashMap<String, String> map1 = new HashMap<String, String>();   
//                  JSONObject e = data.getJSONObject(i);
//                  
//                  map1.put("id", String.valueOf(i));
//                  map1.put("name", "" + e.getString("ServUser"));
//                  map1.put("email", "" + e.getString("ServURL"));
//                  mylist.add(map1);
//              }       
//          
//      } catch (JSONException e) {
//          // TODO Auto-generated catch block
//          e.printStackTrace();
//      }


         ListAdapter adapter = new SimpleAdapter(this, mylist , R.layout.item_list,
                                  new String[] { "name", "email" }, 
                              new int[] { R.id.item_title, R.id.item_subtitle });
                                  setListAdapter(adapter);


      final ListView lv = getListView();
       lv.setTextFilterEnabled(true);   
        lv.setOnItemClickListener(new OnItemClickListener() {
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {              
                //@SuppressWarnings("unchecked")
                //HashMap<String, String> o = (HashMap<String, String>) lv.getItemAtPosition(position);                 
            //  Toast.makeText(ListJson.this, "ID '" + o.get("id") + "' was clicked.", Toast.LENGTH_SHORT).show(); 

                Toast.makeText(getApplicationContext(), parent.getItemAtPosition(position).toString(),
                        Toast.LENGTH_LONG).show();

            //   String a= parent.getItemAtPosition(position).toString();

                Intent intent2= new Intent(ListJson.this, ListJson2.class);
                 startActivity(intent2);
            }
        }); 

    }

我收到 OutOfMemoryException。我将 heap_size 更改为 192MB,将 ram 大小更改为 32MB,但没有成功。我该如何解决这个问题?

I am doing a project where I need to parse JSON from a URL through HttpClient. My code works fine for JSON object responses with a small amount of data. But when I use the same code to get a response with a huge amount of data (more than 3MB), I have a problem.

Here is my code:

JSONfunctions.java (function for json parsing)

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
//import java.util.HashMap;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
//import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
//import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import android.util.Log;
import android.widget.Toast;

@SuppressWarnings("unused")
public class JSONfunctions {

    public static JSONObject getJSONfromURL(String url){
        InputStream is = null;
        String result = "";
        JSONObject jArray = null;

        //http post
        try{
                HttpClient httpclient = new DefaultHttpClient();
                HttpPost httppost = new HttpPost(url);
                HttpResponse response = httpclient.execute(httppost);
                HttpEntity entity = response.getEntity();
                is = entity.getContent();

        }catch(Exception e){
                Log.e("log_tag", "Error in http connection "+e.toString());
        }

        //convert response to string
        try{
                BufferedReader reader = new BufferedReader(new InputStreamReader(is,"iso-8859-1"),8);
                StringBuilder sb = new StringBuilder();
                String line = null;
                while ((line = reader.readLine()) != null) {
                        sb.append(line + "\n");
                }
                is.close();
                result=sb.toString();

            //    Toast.makeText(getBaseContext, result, Toast.LENGTH_LONG).

        }catch(Exception e){
                Log.e("log_tag", "Error converting result "+e.toString());
        }

        try{

            jArray = new JSONObject(result);            
        }catch(JSONException e){
                Log.e("log_tag", "Error parsing data "+e.toString());
        }

        return jArray;
    }
}

ListJson.java

import java.util.ArrayList;
import java.util.HashMap;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
//import org.w3c.dom.Document;
//import org.w3c.dom.Element;
//import org.w3c.dom.NodeList;



import android.app.ListActivity;
import android.content.Intent;
//import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ListAdapter;
import android.widget.ListView;
import android.widget.SimpleAdapter;
import android.widget.Toast;


public class ListJson extends ListActivity {
     public static JSONObject json;
     public static JSONArray data;
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.list1);

        ArrayList<HashMap<String, String>> mylist = new ArrayList<HashMap<String, String>>();
     //   String semail = "[email protected]";
      //  String spassword = "partha123";


      //  Toast.makeText(getApplicationContext(), JSONExample2.strEmail, Toast.LENGTH_LONG).show();
        //Toast.makeText(getApplicationContext(), JSONExample2.strPwd, Toast.LENGTH_LONG).show();

        //    

        json = JSONfunctions.getJSONfromURL("url here");      


            try{

            data = json.getJSONArray("server_list");


            for(int i=0;i<data.length();i++){                       
                HashMap<String, String> map = new HashMap<String, String>();    
                JSONObject e = data.getJSONObject(i);

                map.put("id", String.valueOf(i));
                map.put("name", "" + e.getString("ServUser"));
                map.put("email", "" + e.getString("ServURL"));
                mylist.add(map);
            }       
        }catch(JSONException e)        {
             Log.e("log_tag", "Error parsing data "+e.toString());
        }


//        try {
//          JSONObject newObject=json.getJSONObject("subscription");
//          JSONArray data1 = newObject.getJSONArray("cust_product");
//          
//          Toast.makeText(getApplicationContext(), data1.toString(), Toast.LENGTH_LONG).show();
//         
//          for(int i=0;i<data1.length();i++){                      
//                  HashMap<String, String> map1 = new HashMap<String, String>();   
//                  JSONObject e = data.getJSONObject(i);
//                  
//                  map1.put("id", String.valueOf(i));
//                  map1.put("name", "" + e.getString("ServUser"));
//                  map1.put("email", "" + e.getString("ServURL"));
//                  mylist.add(map1);
//              }       
//          
//      } catch (JSONException e) {
//          // TODO Auto-generated catch block
//          e.printStackTrace();
//      }


         ListAdapter adapter = new SimpleAdapter(this, mylist , R.layout.item_list,
                                  new String[] { "name", "email" }, 
                              new int[] { R.id.item_title, R.id.item_subtitle });
                                  setListAdapter(adapter);


      final ListView lv = getListView();
       lv.setTextFilterEnabled(true);   
        lv.setOnItemClickListener(new OnItemClickListener() {
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {              
                //@SuppressWarnings("unchecked")
                //HashMap<String, String> o = (HashMap<String, String>) lv.getItemAtPosition(position);                 
            //  Toast.makeText(ListJson.this, "ID '" + o.get("id") + "' was clicked.", Toast.LENGTH_SHORT).show(); 

                Toast.makeText(getApplicationContext(), parent.getItemAtPosition(position).toString(),
                        Toast.LENGTH_LONG).show();

            //   String a= parent.getItemAtPosition(position).toString();

                Intent intent2= new Intent(ListJson.this, ListJson2.class);
                 startActivity(intent2);
            }
        }); 

    }

I am getting an OutOfMemoryException. I changed heap_size to 192MB and ram size to 32MB, but with no luck. How can I fix this?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

坚持沉默 2024-11-16 15:26:29

大量的 JSON 数据必须被切割成更小的部分。例如,您的数据库中有 50000 个产品。那么明智的做法是对 API 请求进行分页 - 通过一次查询获取 100-500 条记录来获取如此大量的产品。那会解决你的问题。

这种方法又解决了一个问题 - 由互联网和 gprs 连接丢失等引起的错误。

如果 API 是你的,那么你可以更改它。如果不是,那么这是 API 设计的一大失败,您可以发送更改请求。

编辑:

做了一点阅读,发现强烈建议解析大量 JSON 数据是 http://jackson.codehaus.org /(杰克逊处理器)。还没有尝试过,所以无法评论这个库。还建议您将此 JSON 流保存到文件中(不要将其加载到内存中),然后按块解析它。

Big amounts of data of JSON must be cut to smaller pieces. For example you have a 50000 products on your database. Then it's wise to paginate API requests - get this huge amount of products by 100-500 records on one query. That will solve your problem.

This approach solves one problem more - errors caused by internet and gprs connection loss etc.

If API is yours then you can change this. If not, then this is a big failure of API design and you can send change request.

EDIT:

Did a little reading and found that highly recommended for parsing huge load of JSON data is http://jackson.codehaus.org/ (Jackson Processor). Haven't tried it, so cannot comment about this library. Also recommend you to save this JSON stream into the file (don't load it to memory) and then parse it by chunks.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文