目录
一:FileInputStream/FileOutputStream
一:FileInputStream/FileOutputStream
首先一点计算机识别的都是二进制,所以来说,读取文件的第一步就是建立文件连接,然后构建字节流通道,java所有的I/O都是字节流开始的,所谓的字符流也是在字节流的基础上进行的字节流转化成字符流的操作。这一点再我的上一篇文章已经说过。
File file = new File("");
#构建字节流通道
FileInputStream fileInputstream= new FileInputStream/(file);
#好了字节流我们已经构建好了,然后就开始读取操作了。下面介绍几种常用的读取方法,并说明注意事项。
fileOutputStream .read():read()无参的这个方法,返回的是你读取的单个字节的十进制表示方式,为什么呢?因为返回二进制你也看不懂那是啥。这个方法调用一次只会返回一个字节,所以你想获取所有的文件内容就得循环获取了,既然循环获取据必须有一个循环终止的点,这个点就是当read()返回-1的时候代表文件读取结束了。下面看我的一个简单的文件复制代码。(希望你自己测试一下,下面代码的功能就是把a.txt的内容逐字节读取出来写入b.txt)
package test; import java.io.*; public class test { private static String a; public static void main(String[] args) throws IOException, InterruptedException { File file = new File("C:\\Users\\Administrator\\Desktop\\a.txt"); FileOutputStream fileOutputStream = new FileOutputStream("C:\\Users\\Administrator\\Desktop\\info1\\b.txt"); FileInputStream fileInputStream =new FileInputStream(file); int b=0; while ((b=fileInputStream.read())!=-1){ fileOutputStream.write(b); } fileInputStream.close(); fileOutputStream.flush(); fileOutputStream.close(); } }
二:改进的复制功能。
上面的功能没问题的,但是我们要向一下,那这个复制是从一个文件逐个字节读取然后逐个字节写入别的文件,你这不是搞笑么,这也太low了吧,最好的方式当然是我们每一可以赋值一大串才对么。对啊,下面我们来看下面的改进版复制功能。话不多说上代码。
public class test { private static String a; public static void main(String[] args) throws IOException, InterruptedException { File file = new File("C:\\Users\\Administrator\\Desktop\\a.txt"); FileOutputStream fileOutputStream = new FileOutputStream("C:\\Users\\Administrator\\Desktop\\info1\\b.txt"); FileInputStream fileInputStream =new FileInputStream(file); byte[] by = new byte[50]; int length=0; while ((length=fileInputStream.read(by))!=-1){ fileOutputStream.write(by,0,length); //fileOutputStream.write(by); } fileInputStream.close(); fileOutputStream.flush(); fileOutputStream.close(); } }
我来解释一下上面的代码:这个代码和上面的区别不大,核心改变就是by[]数组,这个的意思就是我现在是一次性读取50个字节,然后将读取的50个字节放在by[]数组中,然后我调用write()方法将这by[]写出到新的文件。
2.1需要注意的地方是
- read(by)这个方法和read()无参的方法不一样,前者是将读取的字节放入by[]中的同时,返回了读取到的字节的个数length 。后者read()是但会读取的当前字节。如果读取结束的话都返回-1.
- 注意我上面代码的注释部分,这是我要说的重点。大家仔细思考上面的代码,我每一次读取的是50个字节,每一次by[]数组的数据会被下一次读取的数据覆盖掉,这个机制是有问题的。
假如我的数据有140个字节,我每次读取50字节。
第一次读取50,没问题。将by[]中的数据写出去,此时by[]数据被写入新的文件,但是by[]里面的数据还在的。
第二次的时候再读取50字节,然后这新的50个字节会一个一个的替换掉第一次by[]的的数据。然后by[]写出去,此时by[]数据依旧在,不过和第一次相比,是第二次的数据了,第一次的数据已经永久消失了,被第二次读取的替换掉了。
第三次:这一次再次读取,等等,数据此时只有40个字节了。ok读取,度去了之后替换第二步的by[]里面的前四十个字节,然后写出去。 到这里你的发现问题没有,因为第三次只覆盖了by[]里面的前四十个字节,此时你要是写出去的话就会有问题。此时你会发现你多写出了一些东西。 因为第二次读取的数据五十个字节都在by[]里面,你覆盖了前四十个还剩下了十个,这十个字节就是你多复制的。 嗯,这就是//fileOutputStream.write(by);这个注释的代码的问题,你不能全部写出去,只写出去前四十个就行了,但是//fileOutputStream.write(by)会将整个by中的数据全部写出去,这就是问题所在了。
实际上前四十个才是我们第三次读取的真实的数据的长度。这就是 fileOutputStream.write(by,0,length);的由来。
今天先到这里,其余的I/O会逐一讲解,see you next.