对于文件必然有读和写的操作,读和写就对应了输入和输出流,流又分成字节和字符流。
1.从对文件的操作来讲,有读和写的操作——也就是输入和输出。
2.从流的流向来讲,有输入和输出之分。
3.从流的内容来讲,有字节和字符之分。
这篇文章先后讲解IO流中的字节流和字符流的输入和输出操作。
一、字节流1)输入和输出流
首先,字节流要进行读和写,也就是输入和输出,所以它有两个抽象的父类InputStream、OutputStream。
2)读写结束
在字节流中当读写结束,达到文件结尾时,称为EOF = End或者读到-1就读到结尾。
3)输入流基本方法
首先我们要清楚输入流是什么。比如通过我们的键盘在文本文件上输入内容,这个过程键盘充当的就是输入流,而不是输出流。因为键盘的功能是将内容输入到系统,系统再写入到文件上。以下是输入流的基本方法read():
.read(.read(byte[] buf,int start, int size)//读取数据到字节数组buf从buf的start位置开始存放size长度分数据
其中in是InputStream抽象类的实例,可以发现这个方法和RandomAccessFile类中的read()方法差不多,因为两者都是通过字节来读取的。
4)输出流基本方法
输出流是进行写的操作,其基本操作方法是write(),可以将此方法与输入read()方法一 一去对应,更好理解。
.write(.write(byte[] buf, int start,int size) //字节数组buf从start位置开始写size长度的字节到流
了解了InputStream、OutputStream的基本操作方法后,再来看看它们两个的“孩子”FileInputStream和FileOutputStream。
这两个子类具体实现了在文件上读取和写入数据的操作,日程编程中更多的是使用这两个类。
二、FileInputStream和FileOutputStream类的使用-----------------FileInputStream类的使用
1.使用read()方法读取文件
* 读取指定文件内容,按照16进制输出到控制台 3 * 并且每输出10个byte换行 FileNotFoundException printHex(String fileName) throws IOException{ FileInputStream in=new FileInputStream(fileName); 9 int b; ((b=in.read())!=-1){ 12 if(b<=0xf){ System.out.println("0"); 15 } 16 System.out.print(Integer.toHexString(b& 0xff)+" "); 17 if(++count%10==0){ 18 System.out.println(); 19 } 20 } }
运行结果(随便一个文件来测试的):
注意:
2.使用read(byte[] buf,int start, int size)方法读取文件
上述方法只能一个一个字节读取,对于较大的文件效率太低,推荐使用这个方法来一次性读取文件。
printHexByBytes(String fileName) throws IOException{ 2 FileInputStream in=new FileInputStream(fileName); [20*1024]; * 从in中批量读取字节,放入到buf这个字节数组中 6 * 从第0个位置开始放,最多放buf.length个 7 * 返回的是读到的字节个数 count=in.read(buf, 0, buf.length); 11 int j=1; 12 for(int i=0;i<count;i++){ 13 if((buf[i]&0xff)<=0xf){ System.out.print("0"); 16 } 17 System.out.print(Integer.toHexString(buf[i]&0xff)+ " "); 18 if(j++%10==0){ 19 System.out.println(); 20 } 21 } 22 in.close(); 23 } 24 }
read(byte[] buf,int start, int size)返回的是读到的字节个数,即buf字节数组的有效长度,所以输出buf数组时用的长度是count而不是buf.length,因为我们不知道文件大小和数组大小的关系,上述方法适用于文件大小不超过数组大小的情况下,一次性把文件内容读取到数组里,这里就有一个问题了,如果文件大小超过数组大小,那又该如何读取才能把文件全部读完呢??
我们知道读到-1就是读到文件末,所以还是利用while循环重复读取直到读到-1结束循环,把上述代码修改后如下:
printHexByBytes(String fileName) throws IOException{ 2 FileInputStream in=new FileInputStream(fileName); [20*1024]; * 从in中批量读取字节,放入到buf这个字节数组中 6 * 从第0个位置开始放,最多放buf.length个 7 * 返回的是读到的字节个数 j=1; b=0; 12 while((b=in.read(buf, 0, buf.length))!=-1){ 13 for(int i=0;i<b;i++){ 14 if((buf[i]&0xff)<=0xf){ System.out.print("0"); 17 } 18 System.out.print(Integer.toHexString(buf[i]&0xff)+ " "); 19 if(j++%10==0){ 20 System.out.println(); 21 } 22 } 23 } 24 in.close(); 25 } 26 }
好了,我们用一个大于数组的文件来测试一下结果(太长,只截图末尾):
大家可以比较两者的不同,第二种优化后更适合日常的使用,因为无论文件大小我们都可以一次性直接读完。
-----------------FileOutputStream类的使用
FileOutputStream类和FileInputStream类的使用相类似,它实现了向文件中写出btye数据的方法。里面的一些细节跟FileInputStream差不多的我就不提了,大家自己可以理解的。
1.构造方法
FileOutputStream类构造时根据不同的情况可以使用不同的方法构造,如:
FileOutputStream out = new FileOutputStream("demo/new1.txt");//以路径名称构造
FileOutputStream out = new FileOutputStream("demo/new1.txt",true);
更多内容可以查询API。
2.使用write()方法写入文件
write()方法和read()相似,只能操作一个字节,即只能写入一个字节。例如:
a=10;out.write(a>>>24); 4 out.write(a>>>16); 5 out.write(a>>>8); 6 out.wirte(a);
每次只写一个字节,显然是不效率的,OutputStream当然跟InputStream一样可以直接对byte数组操作。
3.使用write(byte[] buf,int start, int size)方法写入文件
意义:把byte[]数组从start位置到size位置结束长度的字节写入到文件中。
语法格式和read相同,不多说明
三、FileInputStream和FileOutputStream结合案例了解了InputStream和OutputStream的使用方法,这次结合两者来写一个复制文件的方法。