BufferedReader.readLine()是否可以在从慢流中读取时不读取整行?

时间:2012-07-03 20:56:35

标签: java io bufferedreader

我在使用我们的某个系统时遇到一个奇怪的错误,我无法解释。在我们的系统中,后端生成一个大的TSV输出文件,然后我们使用以下代码在HTTP上提供服务:

    BufferedInputStream input = new BufferedInputStream(p.getInputStream(), (int)FileUtils.BYTES_PER_MEGABYTE * 16);
    OutputStream output = resp.getOutputStream();
    byte[] buffer = new byte[(int) (FileUtils.BYTES_PER_KILOBYTE * 8)];
    do
    {
        int read = input.read(buffer);
        if (read <= 0) break;
        output.write(buffer);           
    } while (true);
    input.close();
    output.close();

然后在客户端有一个消耗HTTP响应的TSV解析器,但是在非常大的输入上,我们开始看到奇怪的工件,解析器将报告一行有错误的项目数,并且错误消息打印出它将生成的行解析并且该行将是随机数据块,即不是数据的整行

我的第一个想法是生成的TSV格式不正确但我通过直接从后端系统复制文件,然后通过三个独立编写的开源TSV解析器(包括客户端)来运行它,这几乎排除了这一点。代码正在使用)并且所有这些代码都能够在本地文件上运行时解析文件。

作为参考,我们使用的TSV解析器的代码是here

这引出了两种可能性:

  1. 我在HTTP上复制文件时所显示的代码在某种程度上存在缺陷 - 在这种情况下,我希望有人能指出我做出的愚蠢但非显而易见的错误!
  2. 消费解析器正在使用的
  3. BufferedReader.readLine()不能保证读取整行?如果是这种情况,我不会完全感到惊讶,因为我已经被.Net中的慢速网络流的奇怪读取行为所困扰,所以想知道类似的问题是否适用于Java?
  4. 还是有其他一些我忽略的解释?

1 个答案:

答案 0 :(得分:1)

在发布此问题时,我突然发现错误是什么(通常!)

我发布的用于复制文件的代码的以下部分不正确:

int read = input.read(buffer);
if (read <= 0) break;
output.write(buffer);

它应该如下:

int read = input.read(buffer);
if (read <= 0) break;
output.write(buffer, 0, read);

问题在于我总是将整个缓冲区写入输出流,即使我们从输入读取的内容少于缓冲区的大小。这意味着在文件的末尾,我们将打印最后一块数据以及剩余缓冲区中剩余的数据,因此剩下的随机数据块就会消失!