0

我正在尝试使用 Android HttpClient 读取相当大的响应正文(视频数据 > 5 MB)。我已经使用 AsyncTask 方法在后台执行网络任务。代码在读取调用时卡住并出现 OutofMemoryError 超时。

我还尝试了默认的 EntityUtils 方法,该方法还返回 OutofMemoryError,这是合理的,因为这是要在内存中读取的相当大量的数据。

为了以防万一,检查它是否是二进制数据有一个小的粗略检查。

关于为什么读取被阻塞的任何想法?

protected HttpResponse doInBackground(String... params) {
        String link = params[0];
        HttpResponse response = null;
        HttpGet request = new HttpGet(link);

        //Just in case we need proxy
        if (isCancelled())
        {
            Log.d(LOGTAG, "Background task cancelled");
        }

        //Start android client for sending first request
        Log.d(LOGTAG, "Proxy is disabled");
        client = AndroidHttpClient.newInstance("Android");
        try 
        {

            response = client.execute(request);
            if(response != null)
            {
                try 
                {
                    //HttpEntity entity = response.getEntity();
                    Log.d(LOGTAG,"Parsing Response");
                    String line = "";

                    // Wrap a BufferedReader around the InputStream

                    InputStream responseStream = response.getEntity().getContent();

                     //This causes OutofMemoryError
                    //responseBody = EntityUtils.toString(getResponseEntity); 

                    int read=0;
                    byte[] bytes = new byte[12288];
                    OutputStream output = null;

                    String filename = searchContentUrl.replace('/', '_');
                    File outfile = new File(AppMainActivity.dataDir, filename);

                    output = new BufferedOutputStream(new FileOutputStream(outfile));
                    int firstChunkCheck = 0;
                    while((read = responseStream.read(bytes))!= -1)
                    {
                        CharsetEncoder encoder =  Charset.forName("ISO-8859-1").newEncoder();  

                        if(binaryData == 0)
                        {
                            if (firstChunkCheck == 0) //Crude check for binary data
                            {  
                                if(encoder.canEncode(new String(bytes)))
                                Log.d(LOGTAG,"Got normal Data");
                                binaryData = 0;
                                firstChunkCheck = 1;
                            }
                            responseBody += new String(bytes);
                        }


                        else 
                        {  
                            //Toast.makeText(getApplicationContext(), "Downloading file ", Toast.LENGTH_SHORT).show();
                            binaryData = 1;
                            Log.d(LOGTAG, "Writing binary file...");
                            try 
                            {
                                output.write(bytes);
                            }
                            catch(FileNotFoundException ex)
                            {
                                Log.d(LOGTAG, "FileNotFoundException");
                                ex.printStackTrace();
                            }
                            catch(IOException ex)
                            {
                                ex.printStackTrace();
                            }
                        }  
                    }
                    if(output != null)
                        output.close();


                    Log.d(LOGTAG,"Read Response");
                    return response;
                }
                catch (ParseException e)
                {
                    Log.d(LOGTAG,"IOException while getting Response");
                    e.printStackTrace();
                    return null;
                }
                catch (UnsupportedEncodingException e) 
                {
                    Log.d(LOGTAG,"UnsupportedEncodingException while decoding uri");
                    e.printStackTrace();
                    return null;
                }
                catch (IOException e) 
                {
                    Log.d(LOGTAG,"IOException while decoding uri");
                    e.printStackTrace();
                    return null;
                }
            }
        } 
        catch (IOException e) 
        {
            e.printStackTrace();
            return null;
        } 
        finally
        {
            //client.close();
        }
        return response;
    }
4

1 回答 1

0

您正在尝试在编写数据时对其进行编码。相反,将原始数据写入文件,然后在读取时对其进行编码。这允许您InputStreamReader为您的特定字符集使用一个,它会为您处理所有细节。正如您可能已经意识到的那样,只有在所有数据都可用时才能这样做。

此外,这条线responseBody += new String(bytes);看起来有点奇怪。

于 2013-09-10T08:10:53.110 回答