Java 在android中从HttpURLConnection获取InputStream时获取未知长度HttpInputStream

Java 在android中从HttpURLConnection获取InputStream时获取未知长度HttpInputStream,java,android,web-services,inputstream,saxparser,Java,Android,Web Services,Inputstream,Saxparser,HttpURLConnection.getInputStream()提供未知长度的httpInputStream,并且由于此文档解析引发SAX解析器异常 下面是代码 try{ URL url = new URL(uri); HttpURLConnection connection = (HttpURLConnection) url.openConnection(); connection.setRequestMethod("GET"); connectio

HttpURLConnection.getInputStream()提供未知长度的httpInputStream,并且由于此文档解析引发SAX解析器异常

下面是代码

try{
    URL url = new URL(uri);
    HttpURLConnection connection =
    (HttpURLConnection) url.openConnection();
    connection.setRequestMethod("GET");
    connection.setRequestProperty("Accept", "application/xml");

    InputStream xml = connection.getInputStream();
    System.out.println(connection.getResponseCode());
    DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
    DocumentBuilder db = dbf.newDocumentBuilder();
    Document doc = db.parse(connection.getInputStream());
    doc.getDocumentElement().normalize();

}catch(Exception e){
    e.printStackTrace();
}
任何人都知道UnknownLengthHttpInputStream的原因。我只在android中遇到这个错误,而这段代码在Java项目中工作得非常好

以下是LogCat的例外情况:

08-08 11:07:40.490: W/System.err(1493): org.xml.sax.SAXParseException: Unexpected end of document
08-08 11:07:40.504: W/System.err(1493): at org.apache.harmony.xml.parsers.DocumentBuilderImpl.parse(DocumentBuilderImpl.java:129)
08-08 11:07:40.510: W/System.err(1493): at javax.xml.parsers.DocumentBuilder.parse(DocumentBuilder.java:107)
08-08 11:07:40.510: W/System.err(1493): at com.example.testws.MainActivity.onCreate(MainActivity.java:59)
08-08 11:07:40.520: W/System.err(1493): at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1047)
08-08 11:07:40.520: W/System.err(1493): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1611)
08-08 11:07:40.520: W/System.err(1493): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1663)
08-08 11:07:40.520: W/System.err(1493): at android.app.ActivityThread.access$1500(ActivityThread.java:117)
08-08 11:07:40.530: W/System.err(1493): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:931)

提前感谢。

您需要在服务中正确关闭输出流以避免此异常。 如果您使用的是第三方库,请确保已设置响应标头

Content-Type
Content-Length
如果您使用的是java服务,则可以从方法中获取内容长度

File.length()

您是否尝试过使用apache库来实现此目的?我建议如下:

try {
        HttpClient client = new DefaultHttpClient();  
        String getURL = "http://www.google.com";
        HttpGet get = new HttpGet(getURL);
        HttpResponse responseGet = client.execute(get);  
        HttpEntity resEntityGet = responseGet.getEntity();  
        if (resEntityGet != null) {  
                    //do something with the response
                    Log.i("GET RESPONSE",EntityUtils.toString(resEntityGet));
                }
} catch (Exception e) {
    e.printStackTrace();
}
然后获取
HttpEntity
本身的流。 Smth类似:

InputStream st = entity.getContent();

这里有更多示例:

要处理响应,请使用此方法,它将处理所有问题

public static ResponseHandler<String> getResponseHandlerInstance(final Handler handler) {
      final ResponseHandler<String> responseHandler = new ResponseHandler<String>() {

         public String handleResponse(final HttpResponse response) {
            Message message = handler.obtainMessage();
            Bundle bundle = new Bundle();
            StatusLine status = response.getStatusLine();
            Log.d(CLASSTAG, " " + HTTPRequestHelper.CLASSTAG + " statusCode - " + status.getStatusCode());
            Log.d(CLASSTAG, " " + HTTPRequestHelper.CLASSTAG + " statusReasonPhrase - " + status.getReasonPhrase());
            HttpEntity entity = response.getEntity();
            String result = null;
            if (entity != null) {
               try {
                  result = HTTPRequestHelper.inputStreamToString(entity.getContent());
                  bundle.putString("RESPONSE", result);
                  message.setData(bundle);
                  handler.sendMessage(message);
               } catch (IOException e) {
                  Log.e(CLASSTAG, " " + HTTPRequestHelper.CLASSTAG, e);
                  bundle.putString("RESPONSE", "Error - " + e.getMessage());
                  message.setData(bundle);
                  handler.sendMessage(message);
               }
            } else {
               Log.w(CLASSTAG, " " + HTTPRequestHelper.CLASSTAG + " empty response entity, HTTP error occurred");
               bundle.putString("RESPONSE", "Error - " + response.getStatusLine().getReasonPhrase());
               message.setData(bundle);
               handler.sendMessage(message);
            }
            return result;
         }
      };
      return responseHandler;
   }

   private static String inputStreamToString(final InputStream stream) throws IOException {
      BufferedReader br = new BufferedReader(new InputStreamReader(stream));
      StringBuilder sb = new StringBuilder();
      String line = null;
      while ((line = br.readLine()) != null) {
         sb.append(line + "\n");
      }
      br.close();
      return sb.toString();
   }
publicstaticresponsehandler getresponsehandler实例(最终处理程序){
最终响应handler ResponseHandler=新响应handler(){
公共字符串句柄响应(最终HttpResponse响应){
Message Message=handler.obtainMessage();
Bundle=新Bundle();
StatusLine status=response.getStatusLine();
Log.d(CLASSTAG,“+HTTPRequestHelper.CLASSTAG+”状态码-“+status.getStatusCode());
Log.d(CLASSTAG,“+HTTPRequestHelper.CLASSTAG+”statusReasonPhrase-“+status.getReasonPhrase());
HttpEntity=response.getEntity();
字符串结果=null;
如果(实体!=null){
试一试{
结果=HTTPRequestHelper.inputStreamToString(entity.getContent());
bundle.putString(“响应”,结果);
message.setData(bundle);
handler.sendMessage(message);
}捕获(IOE异常){
Log.e(CLASSTAG,“+HTTPRequestHelper.CLASSTAG,e);
bundle.putString(“响应”,“错误-”+e.getMessage());
message.setData(bundle);
handler.sendMessage(message);
}
}否则{
Log.w(CLASSTAG,“+HTTPRequestHelper.CLASSTAG+”空响应实体,发生HTTP错误);
bundle.putString(“RESPONSE”,“Error-”+RESPONSE.getStatusLine().getReasonPhrase());
message.setData(bundle);
handler.sendMessage(message);
}
返回结果;
}
};
返回应答器;
}
私有静态字符串inputStreamToString(最终InputStream流)引发IOException{
BufferedReader br=新的BufferedReader(新的InputStreamReader(流));
StringBuilder sb=新的StringBuilder();
字符串行=null;
而((line=br.readLine())!=null){
sb.追加(第+行“\n”);
}
br.close();
使某人返回字符串();
}

当SAX解析器无法获取
InputStream
数据的长度时,问题就出现了。要解决此问题,请将从
xml
InputStream
)读取的内容保存到字符串变量中,并从
DocumentBuilder
parse
方法的变量中生成
InputStream
。要执行此操作,请按如下方式修改代码:

try {
            URL url = new URL(uri);
            HttpURLConnection connection = (HttpURLConnection) url.openConnection();
            connection.setRequestMethod("GET");
            connection.setRequestProperty("Accept", "application/xml");
            InputStream xml = connection.getInputStream();

            DataInputStream dis = new DataInputStream(xml);
            StringBuilder sb = new StringBuilder();
            int asci = dis.read();
            while (asci > 0) {
                sb.append((char) asci);
                asci = dis.read();
            }
            String inputXML = sb.toString();            
            String predefinedXML = "<?xml version=\"1.0\" encoding=\"UTF-8\"?> <EmotionDB></EmotionDB>";
            InputStream inputStream = new ByteArrayInputStream(inputXML.getBytes());//use predefinedXML.getBytes() instead of inputXML.getBytes() for sample test


            System.out.println(connection.getResponseCode());
            DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
            DocumentBuilder db = dbf.newDocumentBuilder();
            Document doc = db.parse(inputStream);
            doc.getDocumentElement().normalize();

        } catch (Exception e) {
            e.printStackTrace();
        }
试试看{
URL=新的URL(uri);
HttpURLConnection connection=(HttpURLConnection)url.openConnection();
connection.setRequestMethod(“GET”);
setRequestProperty(“接受”、“应用程序/xml”);
InputStream xml=connection.getInputStream();
DataInputStream dis=新的DataInputStream(xml);
StringBuilder sb=新的StringBuilder();
int asci=dis.read();
而(asci>0){
sb.追加((char)asci);
asci=dis.read();
}
字符串inputXML=sb.toString();
字符串预定义XML=“”;
InputStream InputStream=new ByteArrayInputStream(inputXML.getBytes());//对于示例测试,请使用预定义的XML.getBytes()而不是inputXML.getBytes()
System.out.println(connection.getResponseCode());
DocumentBuilderFactory dbf=DocumentBuilderFactory.newInstance();
DocumentBuilder db=dbf.newDocumentBuilder();
文档doc=db.parse(inputStream);
doc.getDocumentElement().normalize();
}捕获(例外e){
e、 printStackTrace();
}
此处,
inputStream
将具有正确的内容长度,因为它是由具有固定字节数的
ByteArrayInputStream
构建的。

一旦这样尝试

if(connection.getResponseCode() ==HttpURLConnection.HTTP_OK){

  InputStream xml = connection.getInputStream();   
  ..........
}else{

//problem in URI/connection .....
}
它可能是Http 1.0(旧服务器或配置错误)服务器,或者没有配置保持活动。在这种情况下,从服务器关闭连接时,流的长度是已知的。尝试指定http1.1并在请求头中保持活动状态(通过谷歌搜索会有所帮助)。只有在服务器响应中指定了content-length属性,您才能提前知道流的长度

解决方法:
将http流完全读入
字节缓冲流
(直到
read()
返回
-1
)。然后将ByteBufferInputStream抛出到您的库中(长度现在已知)

从logcat附加异常?@Jens我从logcat附加了异常。.您得到了
未知长度HttpInputStream
流,因为您的服务器没有提供
内容长度或使用分块传输编码。当服务器不提供这两种服务时,它必须通过关闭连接来发出HTTP正文结束的信号——在本例中,它似乎是这样做的。你有没有可能嗅探网络服务器