如何从下载文件数据丢失来分析BufferedOutputStream源码
发表于:2025-02-04 作者:千家信息网编辑
千家信息网最后更新 2025年02月04日,如何从下载文件数据丢失来分析BufferedOutputStream源码,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。今天突然遇到一
千家信息网最后更新 2025年02月04日如何从下载文件数据丢失来分析BufferedOutputStream源码
如何从下载文件数据丢失来分析BufferedOutputStream源码,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。
今天突然遇到一个问题,通过下载文件的接口下载的文件比实际文件小了2kb,而且文件中的内容比实际内容少了很多,带着这个问题,我跟踪代码执行流程,我们来看一下核心代码:
bis = new BufferedInputStream(new FileInputStream(targetFilePath)); bos = new BufferedOutputStream(response.getOutputStream()); byte[] buff = new byte[2048]; int bytesRead; while (-1 != (bytesRead = bis.read(buff, 0, buff.length))) { bos.write(buff, 0, bytesRead); }
核心代码非常简单,就是根据目标文件,通过FileInputStream流来读取目标文件流,写入到response的输出流中。中间通过BufferedInputStream和BufferedOutputStream缓冲流来提高性能。 根据上述代码,我大胆猜测可能出现问题的原因是BufferedInputStream或者BufferedOutputStream。进一步分析:
while (-1 != (bytesRead = bis.read(buff, 0, buff.length)))
该语句是循环读取所有读缓冲区的内容,因此,该语句出现问题的几率不是很大,很大可能是因为写缓冲区的问题,下面我通过分析BufferedOutputStream的源码来看看能不能找出问题的原因:
BufferedOutputStream位于 java.io包下 /** * 继承自FilterOutputStream(FilterOutputStream有一个 OutputStream的属性,就是目标输出out对象流) */ public class BufferedOutputStream extends FilterOutputStream { /** * 用来存储数据的缓冲区(默认8912个字节) */ protected byte buf[]; /** * 当前已存储数据的字节数(个人理解为指向已存储数据末尾的一个指针) */ protected int count; /** * 构造方法1: 用设置目标输出流对象,同时默认buff缓冲区大小8912个字节 */ public BufferedOutputStream(OutputStream out) { this(out, 8192); } /** * 构造方法2:设置输出流对象,自定义缓冲区的大小, */ public BufferedOutputStream(OutputStream out, int size) { super(out); if (size <= 0) { throw new IllegalArgumentException("Buffer size <= 0"); } buf = new byte[size]; } /** * 刷新缓冲区(将缓冲区内容写入到目标流对象中,同同时将count置为0) **/ private void flushBuffer() throws IOException { if (count > 0) { out.write(buf, 0, count); count = 0; } } /** * 向缓冲区写一个字节数据 **/ public synchronized void write(int b) throws IOException { //先判断缓冲区是否已满,如果已满,清空缓冲区 if (count >= buf.length) { flushBuffer(); } buf[count++] = (byte)b; } /** * 向缓冲区写入指定长度的数据 **/ public synchronized void write(byte b[], int off, int len) throws IOException { //判断写入数据的长度是否超过缓冲区大小,如果超过,直接写入目标对象out流中,清空缓冲区 if (len >= buf.length) { flushBuffer(); out.write(b, off, len); return; } //如果长度大于缓冲区剩余空间,将缓冲区清空,写入数据 if (len > buf.length - count) { flushBuffer(); } System.arraycopy(b, off, buf, count, len); count += len; } /** *刷新缓冲区 **/ public synchronized void flush() throws IOException { flushBuffer(); out.flush(); } }
从上面的源码中可以发现:触发缓冲区刷新的时机是当写入数据大小大于缓冲区的可用大小。
为了解决该问题,将核心操作放到try-catche-finally中,在finally中手动关闭BufferedInputStream和BufferedOutputStream流(BufferedOutputStream并没有close方法,调用父类FilterOutputStream的close方法),在关闭前会强制刷新缓冲区的数据到out写对象流中。该问题得到解决。
关于如何从下载文件数据丢失来分析BufferedOutputStream源码问题的解答就分享到这里了,希望以上内容可以对大家有一定的帮助,如果你还有很多疑惑没有解开,可以关注行业资讯频道了解更多相关知识。
缓冲
缓冲区
数据
问题
文件
分析
大小
对象
方法
目标
源码
代码
内容
字节
输出
核心
长度
存储
很大
原因
数据库的安全要保护哪些东西
数据库安全各自的含义是什么
生产安全数据库录入
数据库的安全性及管理
数据库安全策略包含哪些
海淀数据库安全审计系统
建立农村房屋安全信息数据库
易用的数据库客户端支持安全管理
连接数据库失败ssl安全错误
数据库的锁怎样保障安全
江苏戴尔服务器服务热线
特效拍照软件开发demo
区块链通信网络技术
软件开发工资计入研发费
肿瘤甲基化数据库
数据库技术三级考试要求
特大网络安全犯罪案例
计算机软件开发一般是谁
支付宝蓝狐网络技术有限公司
早期网络技术包括
苹果软件开发商电话
严谨的软件开发态度
网络安全紧急会议
网络安全事故预防与处置
nginx服务器管理
学校国家网络安全周活动计划
嵌入式系统方向与软件开发
网络安全基础教材电子书
互联网网络安全的特点
计算机网络技术职业目标设定
下列属于网络技术发展阶段的
域中服务器三种角色的区别
衢州电子网络技术优势
什么是网络安全图片
网络安全监测就业前景分析
河南专业服务器散热器加工
吴江区专业性网络技术服务电话
乐山ibm服务器机柜
软件开发成本测算需求要求
给数据库用户读表权限