首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >GZIPInputStream -腐败的GZIP拖车

GZIPInputStream -腐败的GZIP拖车
EN

Stack Overflow用户
提问于 2013-10-12 01:33:33
回答 1查看 10K关注 0票数 2

我有一个静态帮助方法,负责从Rails应用程序获取压缩的JSON字符串,并在返回String表示之前对数据进行解压缩。

我编写了两个JUnit测试,一个测试JSON正确解析的JSON,另一个更基本的测试确定是否从服务器返回长度大于零的字符串。

问题:当我运行测试套件时,第一个测试方法成功了,另一个测试方法在IOException和消息“损坏的GZIP预告片”中失败(参见下面的代码)。我已经确定,失败的并不是测试本身,因为当我使测试以相反的顺序运行时,“成功”测试就会发生逆转(换句话说,无论第二个测试是第二个失败的,无论哪一个测试是第二次测试,它总是失败的)。

这是helper方法:

代码语言:javascript
复制
public static String doHTTPGet(String urlString) throws IOException{
    URL weatherAPI = new URL(urlString);
    HttpURLConnection apiConnection = (HttpURLConnection) weatherAPI.openConnection();
    apiConnection.setRequestMethod("GET");
    apiConnection.setRequestProperty("Accept-Encoding", "gzip");

    apiConnection.connect();

    BufferedInputStream bufferedInputStream = new BufferedInputStream(apiConnection.getInputStream());
    byte[] inputByteBuffer = new byte[10 * 1024];
    ByteArrayOutputStream outputStream = new ByteArrayOutputStream(10 * 1024); // initialize the output stream with at least one buffer's worth of bytes
    while(bufferedInputStream.read(inputByteBuffer)  > -1){
        outputStream.write(inputByteBuffer);
    }

    outputStream.close();
    bufferedInputStream.close();
    apiConnection.disconnect();

    ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(outputStream.toByteArray());
    byteArrayInputStream.close();

    GZIPInputStream gis = new GZIPInputStream(byteArrayInputStream);
    InputStreamReader inputStreamReader = new InputStreamReader(gis, "UTF-8");
    BufferedReader reader = new BufferedReader(inputStreamReader);

    String decompressedResponse = "";
    String line;

    // readLine() is generating the IOException on the second pass.
    while((line = reader.readLine()) != null){
        decompressedResponse += line;
    }

    reader.close();
    inputStreamReader.close();
    gis.close();

    return decompressedResponse;
}

该错误发生在while((line = reader.readLine()) != null)...行的helper方法的底部。具体来说,错误发生在reader.readLine()上。

这两种测试方法:

代码语言:javascript
复制
@Test
public void testHttpGet(){
    try {
        // FILTERED_API_URL_WITH_TOKEN is merely the URL with an auth token
        String apiResponse = HTTPHelper.doHTTPGet(GlobalConstants.FILTERED_API_URL_WITH_TOKEN);
        assertNotNull(apiResponse);
        assertTrue("The size of the API response should be greater than zero. It is an empty string.", apiResponse.length() > 0);
    } catch (IOException e) {
        e.printStackTrace();
        assertTrue("An exception occured while trying to perform the HTTP Get to the api at URL " + GlobalConstants.FILTERED_API_URL_WITH_TOKEN, false);
    }
}

@Test
public void testAPIContent(){
    try {
        // the getAPIJson() method basically does the same as the testHttpGet
        // method, but converts the string to a json
        JSONObject jsonObject = XMLProducerFromAPI.getAPIJson();
        System.out.println(jsonObject);
        assertNotNull(jsonObject);
    } catch (IOException e) {
        e.printStackTrace();
        assertTrue("An IOException occured. See stack trace", false);
    } catch (JSONException e) {
        e.printStackTrace();
        assertTrue("A JSONException occured. See stack trace", false);
    }
}

我读过this questionthe answer,但我不相信它适用,(或者可能是,我误解了,如果是这样的话,请告诉我),我尝试了他们的方法,只收到了同样的信息。

由于doHTTPGet方法是静态的,并且所创建的对象是在方法主体内创建的,因此不应该重用任何东西(流、连接对象等)。坦白说我很困惑。

问题:我是否在我的助手代码中做错了什么,或者我是否误解了某些对象的某些用法,从而产生了“损坏的GZIP拖车”消息?简而言之,在我的场景中,是什么导致了这个错误?

和往常一样,如果我遗漏了什么问题,请告诉我。

编辑

这是堆栈跟踪:

代码语言:javascript
复制
java.io.IOException: Corrupt GZIP trailer
    at java.util.zip.GZIPInputStream.readTrailer(GZIPInputStream.java:200)
    at java.util.zip.GZIPInputStream.read(GZIPInputStream.java:92)
    at sun.nio.cs.StreamDecoder.readBytes(StreamDecoder.java:264)
    at sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:306)
    at sun.nio.cs.StreamDecoder.read(StreamDecoder.java:158)
    at java.io.InputStreamReader.read(InputStreamReader.java:167)
    at java.io.BufferedReader.fill(BufferedReader.java:136)
    at java.io.BufferedReader.readLine(BufferedReader.java:299)
    at java.io.BufferedReader.readLine(BufferedReader.java:362)
    at com.weathertx.xmlserver.support.HTTPHelper.doHTTPGet(HTTPHelper.java:60)
    at com.weathertx.xmlserver.tests.HttpHelperTest.getAPIResponse(HttpHelperTest.java:47)
    at com.weathertx.xmlserver.tests.HttpHelperTest.testHttpGet(HttpHelperTest.java:21)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:47)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44)
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
    at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:271)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:70)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:309)
    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
    at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2013-10-18 19:52:46

问题已经解决了。坦率地说,我不太明白为什么它一开始就行不通,或者它有什么问题(除了显然过于复杂和不必要的复杂)。多亏了this solution,我以某种方式错过了第一次搜索,我基本上能够解决问题,基本上完全实现了他们所做的事情。这是我的最后代码:

代码语言:javascript
复制
public static String doHTTPGet(String urlString) throws IOException{
    URL weatherAPI = new URL(urlString);
    HttpURLConnection apiConnection = (HttpURLConnection) weatherAPI.openConnection();
    apiConnection.setRequestMethod("GET");
    apiConnection.setRequestProperty("Accept-Encoding", "gzip");

    apiConnection.connect();

    InputStream gzippedResponse = apiConnection.getInputStream();
    InputStream decompressedResponse = new GZIPInputStream(gzippedResponse);
    Reader reader = new InputStreamReader(decompressedResponse, "UTF-8");
    StringWriter writer = new StringWriter();

    char[] buffer = new char[10240];
    for(int length = 0; (length = reader.read(buffer)) > 0;){
        writer.write(buffer, 0, length);
    }

    writer.close();
    reader.close();
    decompressedResponse.close();
    gzippedResponse.close();
    apiConnection.disconnect();

    return writer.toString();
}

因此,最终,我不需要通过字节数组流和各地传递数据。除了我最初的方法令人费解外,如果有人具体知道为什么我的原始算法在第一次调用之后产生了“损坏的GZIP预告片”错误消息,请务必通知我。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/19329517

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档