使用缓冲Buffered流复制文件时,文件大小不一样的问题
在用java批量复制文件时,用的是带缓冲区的字符流,结果复制后的文件比原来的文件要大,代码如下:
public static void main(String[] args) throws IOException { File file = new File("D:\\aaa\\原文件.PDF"); String fileName = "D:\\aaa\\复制的文件"; for(int i=0;i < 10; i++){ // FileUtils.copyFile(file, new File(fileName + i + ".PDF")); BufferedReader reader = new BufferedReader(new FileReader(file)); BufferedWriter writer = new BufferedWriter(new FileWriter(new File(fileName + i + ".PDF"))); String data = null; while((data = reader.readLine()) != null){ writer.write(data); writer.newLine(); writer.flush(); } writer.close(); reader.close(); // BufferedInputStream input = new BufferedInputStream(new FileInputStream(file)); // BufferedOutputStream output = new BufferedOutputStream( // new FileOutputStream(new File(fileName + i + ".PDF"))); // // int len = -1; // byte[] data = new byte [1024];//一次读取1M // while ((len = input.read(data)) != -1){ // output.write(data,0,len); // } // // output.close(); // input.close(); System.out.println("复制了第:" + i + " 个文件"); } System.out.println("复制完成!"); }
复制后的效果如下图:
可以发现,复制后的文件大小和原文件是不一样的,这里是因为我复制的是PDF文件,而不是普通的文本文件,所以这里不能使用字符流BufferedReader,而应该使用字节流inputStream
下面总结一下字节流与字符流的区别与各自的使用场景:
- Java 中的字节流处理的最基本单位为 1 个字节,通常用来处理二进制数据。字节流类 InputStream 和 OutputStream 类均为抽象类,代表了基本的输入字节流和输出字节流。
- Java 中的字符流处理的最基本的单元是 Unicode 代码单元(大小2字节),通常用来处理文本数据。
区别:
- 字节流操作的基本单元是字节;字符流操作的基本单元是字符
- 字节流默认不使用缓冲区;字符流使用缓冲区
- 字节流通常用于处理二进制数据,不支持直接读写字符;字符流通常用于处理文本数据
- 在读写文件需要对文本内容进行处理:按行处理、比较特定字符的时候一般会选择字符流;仅仅读写文件,不处理内容,一般选择字节流
特征:
- 以 stream 结尾都是字节流,reader 和 writer 结尾是字符流
- InputStream 是所有字节输入流的父类,OutputStream 是所有字节输出流的父类
- Reader 是字符输入流的父类,Writer 是字符输出流的父类
常见的字节流:
- 文件流:FileOutputStream 和 FileInputStream
- 缓冲流:BufferedOutputStream 和 BufferedInputStream
- 对象流:ObjectOutputStream 和 ObjectInputStream
常见的字符流:
- 字节转字符流:InputStreamReader 和 OutputStreamWriter
- 缓冲字符流:PrintWriter 和 BufferedReader
可以这样理解文件复制的过程:
字符流:二进制数据 --编码-> 字符编码表 --解码-> 二进制数据
字节流:二进制数据 —> 二进制数据
所以问题就是出现在编码和解码的过程中,既然是字符的编码表,那它就是包含所有的字符,但是字符的数量是有限的,这就意味着它不能表示一些超过编码表的字符,因为根本不存在表中。所以,JVM 会使用一些字符进行替换,基本上都是乱码(所以大小会发生变化),而且如果有一个数据恰好是-1,那么读取就会中断,引起数据丢失。
分类:
java
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构