2012-02-29 31 views
2

我正在开发一个应用程序,首次启动时,我预计会以​​JSON格式(比如10-20 MB)下载大量数据。所有这些数据都在单个网络请求中传输(原因是数据是按请求动态生成的)。接收数据(in builder.append())时,fllowing代码抛出OOM异常:当从Android应用程序发出大型网络请求时避免OutOfMemory异常

public static String readToString(InputStream stream) throws IOException { 
    BufferedReader in = null; 
    StringBuilder builder = new StringBuilder(); 
    in = new BufferedReader(new InputStreamReader(stream, "UTF-8")); 
    char[] buffer = new char[1024]; 
    int read = 0; 
    while ((read = in.read(buffer, 0, 1024)) > 0) { 
     builder.append(buffer, 0, read); 
    } 
    in.close(); 
    return builder.toString(); 
    } 

我能做些什么来避免这个错误?我正在考虑将数据保存到临时文件然后处理它。但我不确定它是否会起作用。 另一种可能性似乎是将网络IO分成两部分:第一部分,应用程序接收有关应下载内容的数据,第二部分实际下载数据。

有什么建议吗?

+0

您可以将数据保存到临时文件。关于方式#2,如果数据也很大,它可能是相同的。所以好方法是临时文件。 – 2012-02-29 09:09:30

+0

将数据保存到本地文件并处理它,我认为这是个好主意。 – idiottiger 2012-02-29 09:09:34

回答

3

按照您的第一个想法 - 将数据保存到一个临时文件(sdcard,请在内部存储20mb太大)。您首先需要打开连接以供下载。

InputStream is = URL("your_request_string").openStream(); 

然后在SD卡

File f = new File(Environment.getExternalStorageDirectory(), "temp.dat"); 

使用新创建的文件中创建一个新的文件,打开的OutputStream。

FileOutputStream = new FileOutputStream(f); 

您现在可以使用这段代码做您的转移:

public static void CopyStream(InputStream is, OutputStream os) { 
    final int buffer_size=8192; 
    try 
    { 
     byte[] bytes=new byte[buffer_size]; 
     for(;;) 
     { 
      int count=is.read(bytes, 0, buffer_size); 
      if(count==-1) 
       break; 
      os.write(bytes, 0, count); 
     } 
    } 
    catch(Exception ex){} 
} 
+0

这是非常好的,但没有解决实际的问题,这是解析一个20Mb的JSON文件。 – njzk2 2012-02-29 16:20:49

+0

我假设你已经在使用某种处理大量数据的json解析器。如果没有,请尝试杰克逊 - http://jackson.codehaus.org/ – josephus 2012-03-01 01:25:48

+0

是的,下载数据并将其作为文件存储在SDCard中没有问题。但是当我读取文件并存储为来自SDCard的自定义类的ArrayList时,它会抛出Outof Memory异常。有没有解决方案? – 2013-10-04 12:32:45