java.io.IOException: Premature EOF

本文解决了一个在HTTP访问第三方系统接口时遇到的小概率异常:java.io.IOException: PrematureEOF。通过修改读取流的方式,使用字符数组替代逐行读取,成功解决了因第三方接口可能未发送完整HTTP协议结束行导致的问题。

http访问第三方系统的接口时,小概率抛出下面的异常:

java.io.IOException: Premature EOF

public static String getHttpsContent(HttpsURLConnection conn,
        String characterCode) throws IOException {
    InputStream inputStream = conn.getInputStream();
    InputStreamReader inputStreamReader = new InputStreamReader(
            inputStream, characterCode);
    BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
    String str = null;
    StringBuffer buffer = new StringBuffer();
    while ((str = bufferedReader.readLine()) != null) {
        buffer.append(str);
    }
    // 释放资源
    bufferedReader.close();
    inputStreamReader.close();
    inputStream.close();
    conn.disconnect();
 
    return buffer.toString();
}

while ((str = bufferedReader.readLine()) != null) {
            buffer.append(str);
        }

while语句有时会抛出异常:

java.io.IOException: Premature EOF

at sun.net.www.http.ChunkedInputStream.readAheadBlocking(ChunkedInputStream.java:565)

搜索发现,这个是普遍性的一个问题,解决方法:

https://stackoverflow.com/questions/13210108/reading-a-web-page-in-java-ioexception-premature-eof

 

修改

public static String getHttpsContent(HttpsURLConnection conn, String characterCode) throws IOException {
    InputStream inputStream = conn.getInputStream();
    InputStreamReader inputStreamReader = new InputStreamReader(
            inputStream, characterCode);
    BufferedReader bufferedReader = new BufferedReader(
            inputStreamReader);
    // fix bug:  java.io.IOException: Premature EOF
    //        at sun.net.www.http.ChunkedInputStream.readAheadBlocking(ChunkedInputStream.java:565)
    // https://stackoverflow.com/questions/13210108/reading-a-web-page-in-java-ioexception-premature-eof
    StringBuffer sb = new StringBuffer();
    int BUFFER_SIZE = 1024;
    char[] buffer = new char[BUFFER_SIZE]; // or some other size,
    int charsRead = 0;
    while ( (charsRead  = bufferedReader.read(buffer, 0, BUFFER_SIZE)) != -1) {
        sb.append(buffer, 0, charsRead);
    }
 
    return sb.toString();
}

搞定。原因是第三方接口可能没有发送http协议需要的结束行。

 The issue for you it may be that the server is not pushing that last end line character

在使用 `URLCOnnection.getInputStream()` 读取网络流时,出现 `java.io.IOException: Premature EOF` 异常通常表示在读取数据时,输入流提前结束,未能读取到预期的数据长度。这种问题在处理 HTTP 响应或读取远程文件时较为常见,可能由多种原因引起。 ### 原因分析 1. **服务器提前关闭连接** 服务器可能在发送完所有数据之前关闭了连接,导致客户端在读取时遇到流提前结束。这可能与服务器端的响应机制或网络不稳定有关。 2. **HTTP 响应不完整** 如果使用 `HttpURLConnection` 并未正确处理响应码或响应头,可能导致读取不完整。例如,未检查 `HTTP 200 OK` 状态码就直接读取流,可能在服务器返回错误时导致流异常。 3. **未正确处理压缩数据流** 如果服务器返回的是压缩格式(如 GZIP),而客户端未使用 `GZIPInputStream` 解压,也可能导致读取过程中出现提前结束的问题。 4. **读取方式不当** 使用 `read()` 或 `readFully()` 方法时,如果未正确处理返回值或未循环读取直到流结束,也可能导致提前 EOF。 ### 解决方法 1. **检查 HTTP 响应状态码** 在读取输入流之前,确保服务器返回了正确的响应码,例如: ```java HttpURLConnection connection = (HttpURLConnection) url.openConnection(); connection.setRequestMethod("GET"); int responseCode = connection.getResponseCode(); if (responseCode == HttpURLConnection.HTTP_OK) { InputStream inputStream = connection.getInputStream(); // 读取数据 } else { // 处理非200响应 } ``` 2. **使用 `BufferedInputStream` 提高读取稳定性** 使用缓冲流可以减少网络波动对读取的影响: ```java InputStream inputStream = new BufferedInputStream(connection.getInputStream()); ``` 3. **处理压缩数据** 如果服务器返回的是 GZIP 压缩数据,需使用 `GZIPInputStream` 解压后再读取: ```java String contentEncoding = connection.getContentEncoding(); if (contentEncoding != null && contentEncoding.contains("gzip")) { inputStream = new GZIPInputStream(inputStream); } ``` 4. **正确循环读取流** 使用 `read()` 方法时,应循环读取直到返回 `-1`(流结束): ```java byte[] buffer = new byte[1024]; int bytesRead; while ((bytesRead = inputStream.read(buffer)) != -1) { // 处理读取到的数据 } ``` 5. **使用 Apache Commons IO 工具类** 可使用 `IOUtils.readFully()` 或 `IOUtils.copy()` 简化读取逻辑并避免手动处理流结束问题: ```java ByteArrayOutputStream output = new ByteArrayOutputStream(); IOUtils.copy(inputStream, output); byte[] data = output.toByteArray(); ``` 6. **增加超时设置** 设置合理的连接和读取超时,避免因网络延迟导致连接中断: ```java connection.setConnectTimeout(10000); connection.setReadTimeout(15000); ``` 7. **检查服务器日志和响应内容** 如果可能,检查服务器端日志以确认是否在发送数据时出现异常或提前关闭连接。 ### 总结 `Premature EOF` 异常通常与流的提前关闭或响应不完整有关。通过检查 HTTP 响应码、处理压缩数据、正确读取流以及设置合理的超时机制,可以有效避免该问题。此外,使用成熟的工具库如 Apache Commons IO 也能简化流处理逻辑[^1]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值