平时写IO相关代码机会挺少的,但却都知道使用BufferedXXXX来读写效率高,没想到里面还有这么多陷阱,这两天突然被其中一个陷阱折腾一下:读一个文件,然后写到另外一个文件,前后两个文件居然不一样?

解决这个问题之后,总结了几个注意点。

注意点一:Reader/Writer读写二进制文件是有问题的 :

上面代码使用BufferedReader一行一行地读取一个文件,然后使用BufferedWriter把读取到的数据写到另外一个文件中。如果文件是ASCCII形式的,则内容还是能够正确读取的。但如果文件是二进制的,则读写后的文件与读写前是有很大区别的。当然,把上面的readLine()换成read(char[])仍然不能正确读写二进制文件的。读写二进制文件请接着看下面注意点。

注意点二:read(byte[] b, int offset, int length)中的offset不是指全文件的全文,而是字节数组b的偏移量

现在已经知道使用Reader/Writer不能正确读取二进制文件,这是因为Reader/Writer是字符流,那就改用字节流ufferedInputStream/BufferedOutputStream,网上搜索到的例子大概是这样的:

每次读1024字节,然后写1024字节。这看似挺正确的,但实际写出来的文件与原文件是不同的。这样就怀疑可能是读写没有接上,因而把代码改成下面的形式:

这是误以为:先读一段,写一段,然后改变偏移量,然后使用新的偏移量再读一段、写一段,直到文件读写完毕。但这是错误的,因为使用BufferedXXX后,里面已经实现了这个过程。而read(byte[] b, int offset, int length)中的offset实际指的是把读到的数据存入到数组b时,从数组的哪个位置(即offset)开始放置数据;同理,write(byte[] b, int offset, int length)就是把b中的数据,从哪个位置(offset)开始写到文件中。

注意点三:使用 length=read (b, 0, 1024)读数据时,应该使用write(b, 0, length)来写

第二个注意点中的第一段代码的做法虽然在网上比较常见,但是有问题的。问题在哪呢?答案是:问题在byte[] b这个数组上。由于二进制文件使用比较工具时,只知道不同、但不能知道哪些不同(是否有更先进的比较工具?)。怎样确定它的不同呢?方法很简单:就把二进制文件改成文本文件就能看出结果了(Reader/Writer这种字符流虽然不能正确读写二进制文件,但InputStream/OutputStream这些字节流能既能正确读写二进制文件,也能正确读写文本文件)。由于使用了每次读1K(1024字节)的方式,所以会看到的结果是:写后的文件后面多出一段,这一段的长度与原文件大小以及b数组的大小有关。为了进一步确定是什么关系,把读的文件内容改为"1234567890123",而把b数组的大小改为10字节,这时结果就出来了:写后的文件内容变成"12345678901234567890",就是读了两遍。多出的内容的根源在这里:b数组的大小是10字节,而要读的内容长度是13字节,那就要读两次,第一次读了前10字节,此时b数组内的元素为前10个字符;再读第二次时,由于可读内容只有3个字符,那b数组的内容只有前3个字符被改变了,后面7个字符仍然保持上一次读取的内容。所以直接采用write(b)的方式,在第二次写文件时,内容就多写了一段不是第二次读取到的内容。

下面是正确的读写(即每次读了多少内容,写入的是多少内容,而不是写入整个数组):

注意点四:flush()和close()

flush()是把写缓冲区内的内容全部”吐“到文件上,如果没有它,就有可能很多内容还存在于写缓冲区内,而不是在文件中,也就是还有丢失的可能。

close()中会调用flush()。它是文件真正完成的标志,文件内容写完成后不关闭文件流,会导致一些”古怪“的问题。这个在网络中的流更能体现。

所以,写文件完成后注意关闭文件读写流。

Java写文件导致io过高_161108、Java IO流读写文件的几个注意点相关推荐

  1. Java学习第十六天——字符流读写文件、字符缓冲流拷贝文件

    字符流读写文件 字符流读数据-按单个字符读取 创建字符流读文件对象: ​ Reader reader = new FileReader("readme.txt"); 调用方法读取数 ...

  2. java解析webp格式图片宽高;java解析webp图片转png格式

    java解析webp格式图片宽高:java解析webp图片转png格式 package 你的包名:***.***.***.***;import java.io.FileInputStream; imp ...

  3. C# IO流读写文件操作

    C# IO流读写文件操作 1.创建文件流 2.创建文件读写器 3.执行读写操作 4.关闭文件读写器和文件流 1.创建文件流 string filePath = AppDomain.CurrentDom ...

  4. 第32天学习打卡(字符流读写文件,字节流读写文件)

    字符流读写文件 创建字符流读文件对象: BufferedReader br = new BufferedReader(new FileReader("readme.txt")); ...

  5. java 写一个HelloJavaWorld你好世界输出到操作系统文件Hello.txt文件中

    package com.beiwo.homework;import java.io.File; import java.io.FileOutputStream; import java.io.IOEx ...

  6. Java.IO 字符流读写文件

    点击上方 IT牧场 ,选择 置顶或者星标 技术干货每日送达! 一.序 上一篇我们谈了 java.IO 文件字节流读写操作(能懂系列Java.io文件字节流读写)大家应该都很熟悉了.但是中文和英文在字符 ...

  7. JAVA NIO文件映射、通道、流读写文件示例

    本例使用FileChannel和 BufferedInputStream等测试对比. TestHandler.java 用于实现动态代理,测试运行效率 package com.test;import ...

  8. java 字符流读取_Java 字符流读写文件

    据说,java读写文件要写很多,贼麻烦,不像c艹,几行代码就搞定.只能抄抄模板拿来用了. 输入输出流分字节流和字符流.先看看字符流的操作,字节转化为字符也可读写. 一.写入文件 1.FileWrite ...

  9. c# 文件流读写文件

    using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.I ...

  10. idea 文件流读取web-inf下的文件_C#初学者教程系列20:Stream流读写

    本文是C#初学者简单教程,这是第20篇.感谢观看,记得关注我,后续还有更多教程文章,谢谢. 本文环境为Visual Studio 2019. 一.介绍 在C#文件操作中,通常使用流来读取和写入文件.流 ...

最新文章

  1. 【Kotlin】Kotlin 中使用 ButterKnife ( 仅用于适配 Kotlin 语言 | 不推荐新项目使用 )
  2. Prism4文档翻译(第四章 第一部分) 转载bluesky234
  3. 在线rss阅读聚合器lilina-0.7安装笔记
  4. 配置jvm堆最大内存eden区与s0或者s1区域比例
  5. Mac下的浏览器速度比较,Chrome 得分最高
  6. Javascript Array对象 sort()方法,记忆方法,方法扩展
  7. go语言中输入的方式,获取用户的输入信息
  8. [转载] vim风格设置
  9. java语法让反编译报错_java 反编译
  10. Matlab R2020b安装
  11. 群发红包 java如何实现_java 微信红包算法代码实现及架构设计
  12. 终端应用安全之网络流量分析
  13. pageX,pageY,screenX,screenY,clientX,和clientY,offsetX ,offsetY,layerX,layerY的使用 和 区别
  14. 《麦田里的守望者》感
  15. windows和linux快捷键
  16. python绘制动态Julia集,超炫酷
  17. 网络抓包工具 wireshark 入门教程
  18. 线性代数学习笔记——第七讲——分块矩阵(干货满满的感觉)
  19. CCPC-Wannafly Comet OJ 夏季欢乐赛(2019)
  20. NAS如何外网访问?手把手教你申请公网IP(收藏)

热门文章

  1. mysql查逻辑表的分片规则_MySQL(19) Mycat分片(分库分表)配置
  2. 怎么实现hover_web前端CSS实现一个粒子动效的按钮
  3. wpf的listbox循环数据滚动_滚动版 CentOS Stream 和 Fedora 的关系
  4. 搭建GitLab+Jenkins持续集成环境图文教程
  5. oracle jdbc jar包_Oracle总结之plsql编程(基础七)
  6. socket 编程入门教程(一)TCP server 端:2、socket与文件描述符
  7. JAGUARSDN1网络的开机自动启动 禁用,WIFI模块的启动关闭控制
  8. java 正则匹配括号是否成对_十分钟学会正则表达式
  9. 【转】三、QT例子-打开一个图片并且显示
  10. 【转】magento性能优化的教程(非常详细)