【问题标题】:Android : Read blocks while reading HTTP responseAndroid:在读取 HTTP 响应时读取块
【发布时间】:2013-09-10 12:50:28
【问题描述】:

我正在尝试使用 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;
    }

【问题讨论】:

    标签: java android inputstream httpresponse androidhttpclient


    【解决方案1】:

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

    另外,responseBody += new String(bytes); 这一行看起来有点奇怪。

    【讨论】:

    • 实际上我只是对第一块数据进行编码以检查它是否是二进制数据...这与读取完全无关..实际上即使我删除了该语句问题仍然是一样的......唯一打印的日志是“解析响应”,之后什么都没有......
    • 感谢您的澄清。我已经相应地编辑了我的答案。
    • 嗯......是的......那行是因为每当我得到一个普通的字符串数据时,我都可以将它完全连接到一个字符串中并在以后使用它,因为我确信它与另一种情况是我得到大视频二进制数据。问题是我既没有得到"Got normal Data"也没有得到"Writing binary file..."日志,这让我相信这是阻塞的read()调用
    • 你对我来说太聪明了。我会留给你的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-11-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多