IO流指的就是输入流和输出流。怎么定义输入和输出流呢,以程序为参考,流入到程序里就是输入流,从程序里面流出去就是输出流。
输入/输出流的介绍:
流有三种分类:
1. 从功能上分为:输入流和输出流。
2.从流结构上分为:字节流和字符流。
3.节点流和过滤流。
说明:上面提到了字节流和字符流。其实字符流就是以字节流为基础的,我们操纵String更加方便啊,所以有了字符流。字节流掌握好以后,字符流就很简单了。
字符流和字节流的说明:
字节流的基础是InputStream和OutputStream。我们并不能new InputStream 和OutputStream.它们都是抽象类,我们实际用的都是它们的子类去实现的。
而字符流的基础是Reader和Writer.它们也都是抽象类。
输出流和输入流的说明
对上图的说明:InputStream和Reader都是输入流,就是从外面进入到程序的。
OutputStream和Writer都是输出流,就是从程序流到外面的。
输入流和输出流的读写逻辑:
输入流的读数据的逻辑:
1.打开流。
2.一点一点读,用while语句去判断,是不是还有。
3.有的话就继续读。
4.读完了就关闭流。
输出流的写数据的逻辑:
1.打开流。
2.一点一点写,用while语句去判断,是不是还有。
3.有的话就继续写。
4.写完了就关闭流。
节点流和过滤流的说明
节点流:从特定的地方读写的流类。例如:磁盘或一块内存区域。
过滤流:使用节点流作为输入或输出。过滤流是使用一个已经存在的输入流或输出流连接创建的。
简单的说:节点流就是直接和目标交互的。过滤流就是对节点流做一些包装,与节点流打交道。
下面画一个图说明一下什么是节点流什么是过滤流:(输入流的方面)
上图中直接与txt文档打交道的是节点流。之后的那两个圆形的就是过滤流。也就是说。过滤流就是对节点流进行包装,使之具备更多的功能。最后流入到我们的java程序。
介绍完了三种分类我们接下来具体讲解:
先讲一下字节流:
字节流里面有一个叫做InputStream这么一个抽象类:
那么为什么定义成抽象类呢?
我们看一下InputStream里面的方法:
很明显里面有一个abstract int read()这么一个抽象方法。所以要定义成抽象类。
我们思考一下为什么上面那张图中只有第一个read方法是抽象类的,而其余两个read方法是具体的。
答案:因为两个具体的read方法都是通过调用那个抽象的方法去实现的。很明显啊,很多子类会去继承InputStream抽象类,然后实现那个抽象的read方法。那么以后我们调用具体的read方法是其实是用的是那个被子类覆写过的那个抽象的read方法。(多么完美啊)。
在给张图解释一下:
太完美了。这样的话,InputStream有很多的子类,有处理字节数组的,有处理网络的,处理文件的。这些子类就可以有自己的read方法。这个抽象的父类提供抽象版本就好。
不需要提供具体版本,即使提供具体版本也是没有任何意义的。
讲到这里给一个案例,演示怎么读取一个文件的。JAVA给我们提供了FileInputStream这个实现InutStream父类的子类来处理文件的读取。
FileInputStream里面的read()方法就是专门用来操纵文件的。
我们看一下FileInputStream中的read()的源代码
很明显这个是native的,是用c写的,我们看不到。
下面这种写法是最标准的写法,是套路,切记。
package com.guigu.shen.File; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; public class FileTest { public static void main(String[] args) throws IOException { InputStream fileInputStream=new FileInputStream("d:/abc/xyz/hello/hello.txt"); //创建字节数组。每次把信息读入到这里 byte[] buffer=new byte[200]; //每次读的实际字节数大小; int lenght=0; /* * lenght=fileInputStream.read(buffer,0,200)是指从"d:abc/xyz/hello/hello.txt"这个文件读数据。每次读的数据都存入到 * buffer里面,buffer数组存放的起始位置是0到200,也就是说,我每次都是读200大小的字节数。然后存放在buffer数组里面。存放的位置是buffer的0到buffer * 的200。定义的buffer的大小是200,那么表示我最多每次读的数据也只有200,不然buffer放不下啊。所以最大只能写0,200; * 然后把我每次读的真实的字节数组的长度赋值给length; * 假设以下两种情况1.d:abc/xyz/hello/hello.txt只有150字节的大小。那么我一次就直接读完了。length的大小是150,再去读那就是返回-1了。 * 2.假设d:abc/xyz/hello/hello.txt的大小是450字节大小。那么第一次读返回的length是200.第二次返回的length也是200 * 第三次返回的length只有50了。第四次返回的length是-1: * * 这里的length永远小于等于read(buffer,0,200)里面的200 * * */ while(-1!=(lenght=fileInputStream.read(buffer,0,200))) { //把每一次读的存放在buffer里面的字节都转换为字符串。 String str=new String(buffer, 0,lenght); System.out.println(str); } fileInputStream.close(); ; } }
这种写法是最通用的,一定要闭着眼睛都能写出来。和集合的重要性是一样的。
接下来将会介绍字节流的OutputStream,和InputStream刚好是反着的。
package com.guigu.shen.File; import java.io.FileOutputStream; import java.io.IOException; public class FileTest { public static void main(String[] args) throws IOException { FileOutputStream fileOutputStream=new FileOutputStream("d:/abc/xyz/hello/hello.txt"); String str="helloword"; //把字符串转变为字节数组 byte[] buffer=str.getBytes(); //把字节数组的内容写入到文件夹中 fileOutputStream.write(buffer); fileOutputStream.close(); } }
02JavaIO详解_IOl流的三种分类以及InputStream和OutputStream
原文:http://www.cnblogs.com/shenxiaoquan/p/5738702.html