本文主要是从我写Java网络编程时使用BufferedInputStream和BufferedOutputStream的时候遇到的bug, 来分析BufferedInputStream和BufferedOutputStream的工作机制和简单的源码分析.
1. bug描述
最近在写一个Java网络编程的程序, 其中涉及文件的传输问题, 选择使用BufferedInputStream和BufferedOutputStream来作为网络通信读取数据的方式.
在进行测试的时候, 大文件(几百兆甚至上G)是没有问题的, 但是偶然间测试小文件(十几B)总是失败.
大文件传输成功, 小文件传输不成功, 这说明并不是代码逻辑上的问题, 而应该是某个细节的问题.
经过一番仔细考虑, 去看了看BufferedOutputStream和BufferedInputStream的源码, 终于发现是缓冲区的问题.
小伙伴在看了这博客之后说, 只描述bug对一个陌生人来说不具有太大的参考意义. 所以在这里我在”bug描述”中将我的服务端(sender)和客户端(receiver)关于读写数据的核心代码贴出来, 以供大家参考.
因为代码逻辑较为麻烦, 并且牵扯的方法的调用也比较多, 所以对部分代码做一个大概的解释.
代码的出错部分节选:
sender.java代码节选
public void sendSection() throws IOException {
// RecieverSectionInfo是一个POJO, 用于存储分片文件的基本信息
for (RecieverSectionInfo sectionInfo : sectionInfoList) {
// 发送分片文件正式内容之前先发送一个包头(含有该分片的基本信息)
String sectionInfoStr = PackageUtil.packageSectionInfo(sectionInfo);
byte[] sendHeader = PackageUtil.addHeader(sectionInfoStr);
recieveOutputStream.write(sendHeader);
// 使用文件随机读写流读取文件内容
String fileName = sendPath + sectionInfo.getTargetFileName();
RandomAccessFile randomAccessFile = new RandomAccessFile(fileName, "rw");
randomAccessFile.seek(sectionInfo.getOffset());
// 传输分片文件内容