21、输入输入(io、nio)的一些知识点小结
2015-04-13 14:46
369 查看
一、常用io类
io包下的类有InputStream和OutputStream这两个处理字节的类。常用的io类中,直接继承自这两个类的就是节点流,而通过FilterInputStream和FilterOutputStream再继承自InputStream和OutputStream的都是处理流。用处理流包装节点流是典型的装饰器模式,具体可看下面两张继承关系图
InputStream类继承树:
OutputStream类继承树:
相对于处理字节,还有两个跟InputStream和OutputStream同级的类,Reader和Writer,这两个类专门负责处理字符。其中File\String\CharArray\Piped开头的都是直接和数据打交道,相当于节点流。其他的比如Bufferd\Print\LineNumber等就相当于是处理流。
处理流,比如DataInputStream,构造时需要传入一个InputStream,其实这里再传入一个处理流也是可以的,但是这个作为参数的处理流还需要传入一个节点流作为构造参数。比如:
RandomAccessFile不说了,跟c中的操作很类似。
二、常用io的缓冲输入输出
由于从IO读取和输出数据是一个很慢的过程,所以为了效率,Java程序一般采用缓冲的方法。针对字节流和字符流分别有BufferedInputStream\BufferdOutputStream和BufferedReader\BufferedWriter这四个处理流。
一种常用的做法是:用Buffered的类包装节点流,再用其他类包装Buffered类,比如BufferedWriter包装FileWriter,PrintWriter包装BufferedWriter,以实现向文件中格式化输出字符。或者BufferedOutputStream包装FileOutputStream,DataOutputStream包装BufferedOutputStream,以实现向文件中写入字节数据。类似做法举一反三不一而足。
三、常用nio类
《Java编程思想》说,nio引入了新的IO类库以提高速度,而且旧IO包也已经用nio重新实现过。
nio的两个关键类是Buffer和Channel,Buffer相当于容器,存放和读取数据,而Channel则是对输入输出的模拟。比如用一个FileInputStream实例的getChannel方法得到一个FileChannel,则可以直接通过这个Channel来读取数据。对应的,用一个FileOutputStream实例的getChannel方法得到一个FileChannel,则可以直接通过这个Channel来写入数据。
Channel的一个特点是map方法,这个方法可以直接把一块数据映射到内存中,只有ByteBuffer可以和Channel交互(读,写),而map方法返回一个MappedByteBuffer类,它是ByteBuffer的子类。
值得注意的是:Channel是一个接口,FileChannel是一个抽象类,里面有很多抽象方法,所以我们用各种类的getChannel得到的都是一个实现了抽象方法的子类,但是是什么子类并无从得知,我们依然按照FileChannel暴露的方法来操作,这就是典型的简单工厂模式。
所谓简单工厂模式:比如一个电脑类Computer,其中有一个打印机类成员对象PrinterA。我们可以这么写:
io包下的类有InputStream和OutputStream这两个处理字节的类。常用的io类中,直接继承自这两个类的就是节点流,而通过FilterInputStream和FilterOutputStream再继承自InputStream和OutputStream的都是处理流。用处理流包装节点流是典型的装饰器模式,具体可看下面两张继承关系图
InputStream类继承树:
OutputStream类继承树:
相对于处理字节,还有两个跟InputStream和OutputStream同级的类,Reader和Writer,这两个类专门负责处理字符。其中File\String\CharArray\Piped开头的都是直接和数据打交道,相当于节点流。其他的比如Bufferd\Print\LineNumber等就相当于是处理流。
处理流,比如DataInputStream,构造时需要传入一个InputStream,其实这里再传入一个处理流也是可以的,但是这个作为参数的处理流还需要传入一个节点流作为构造参数。比如:
DataInputStream dis = new DataInputStream(new DataInputStream(new FileInputStream(".\\src\\FinalTest.java")));这样的代码是正确且有效的。
RandomAccessFile不说了,跟c中的操作很类似。
二、常用io的缓冲输入输出
由于从IO读取和输出数据是一个很慢的过程,所以为了效率,Java程序一般采用缓冲的方法。针对字节流和字符流分别有BufferedInputStream\BufferdOutputStream和BufferedReader\BufferedWriter这四个处理流。
一种常用的做法是:用Buffered的类包装节点流,再用其他类包装Buffered类,比如BufferedWriter包装FileWriter,PrintWriter包装BufferedWriter,以实现向文件中格式化输出字符。或者BufferedOutputStream包装FileOutputStream,DataOutputStream包装BufferedOutputStream,以实现向文件中写入字节数据。类似做法举一反三不一而足。
三、常用nio类
《Java编程思想》说,nio引入了新的IO类库以提高速度,而且旧IO包也已经用nio重新实现过。
nio的两个关键类是Buffer和Channel,Buffer相当于容器,存放和读取数据,而Channel则是对输入输出的模拟。比如用一个FileInputStream实例的getChannel方法得到一个FileChannel,则可以直接通过这个Channel来读取数据。对应的,用一个FileOutputStream实例的getChannel方法得到一个FileChannel,则可以直接通过这个Channel来写入数据。
Channel的一个特点是map方法,这个方法可以直接把一块数据映射到内存中,只有ByteBuffer可以和Channel交互(读,写),而map方法返回一个MappedByteBuffer类,它是ByteBuffer的子类。
值得注意的是:Channel是一个接口,FileChannel是一个抽象类,里面有很多抽象方法,所以我们用各种类的getChannel得到的都是一个实现了抽象方法的子类,但是是什么子类并无从得知,我们依然按照FileChannel暴露的方法来操作,这就是典型的简单工厂模式。
所谓简单工厂模式:比如一个电脑类Computer,其中有一个打印机类成员对象PrinterA。我们可以这么写:
Computer c = new Computer(); c.printer = new PrinterA();有一天我们想把所有Computer类对象里的Printer换成PrinterB,那么就要修改所有写了new PrinterA()。在大型项目里这是非常低效繁琐的。我们可以改为Computer有一个Printer对象,PrinterA和PrinterB都是Printer的子类,写一个PrinterFactory类,其中getPrinter方法会返回一个PrinterA对象。
Computer c = new Computer(); c.printer = PrinterFactory.getPrinter();那么,以后想要修改Computer的Printer,只需要修改工厂类里面的getPrinter方法让它返回一个PrinterB就可以了。
相关文章推荐
- Java-IO输入与输出 知识点
- Java IO 相关的知识点小结
- 一、javaSE (二十二)登录注册IO版本案例、数据操作流、内存操作流、打印流、标准输入输出流、随机访问流、合并流、序列化流、Properties、NIO
- java.nio(新IO)小结:
- python的一些知识点小结(1)
- 【Java面试知识点】IO和NIO
- Lua中关于元方法的一些知识点小结
- iOS的一些偏门知识点小结
- io知识点总结和一些看法!
- 我所理解的IO基础:IO、NIO、AIO的一些基本概念
- JS的一些知识点小结
- 2013-05-10 小结 Android的一些知识点
- Android学习之路小结1(加一些小知识点)
- 小结:前几个练习的小结和一些知识点
- 一些小知识点小结
- Android开发中的一些小知识点记录(21-40)
- java输入与输出的格式已经一些知识点
- 【转载】J2SE知识点归纳笔记(七)---Java IO Part 2:获取键盘输入与IO流体系图
- 关于项目中使用的关于nio client的一些小结
- 调用DLL动态库一些小结知识点!