我在使用我们的某个系统时遇到一个奇怪的错误,我无法解释。在我们的系统中,后端生成一个大的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
这引出了两种可能性:
BufferedReader.readLine()
不能保证读取整行?如果是这种情况,我不会完全感到惊讶,因为我已经被.Net中的慢速网络流的奇怪读取行为所困扰,所以想知道类似的问题是否适用于Java?还是有其他一些我忽略的解释?
答案 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);
问题在于我总是将整个缓冲区写入输出流,即使我们从输入读取的内容少于缓冲区的大小。这意味着在文件的末尾,我们将打印最后一块数据以及剩余缓冲区中剩余的数据,因此剩下的随机数据块就会消失!