Java的I/O操作包在java.io下,里面有很多类,大概可以分为以下4类:
1.字节操作的I/O接口:InputStream 和OutputStream 2.字符操作的I/O接口:Writer ,Reader 3.磁盘操作的I/O接口:File 4.网络操作的I/O接口:Socket (Socket不在java.io包下,但也跟I/O有很大关系) 总结起来就是传输数据的数据格式和传输数据的方式这两种,所以说I/O的核心问题要么是数据格式影响I/O操作,要么是传输方式影响I/O操作(《深入分析Java Web技术内幕》)。
1.基本I/O 网络传输和磁盘存储的最小单元是字节,但是在程序中通常的操作数据形式是字符,所以就有了字节与字符的转化。在这个转化过程中,有一点需要注意的是编码的转换,这是个经常会遇到的问题,所以解决乱码问题是Java中的一个大头。
转换接口有 InputStreamReader/OutputStreamWriter,中间用到了适配器模式。InputStreamReader实现了Read接口,并且持有了InputStream的引用(通过StreamDecoder,此类用来编码)。
2.磁盘I/O 几种访问文件的方式 1)标准访问文件方式
应用程序调用系统的read()和wirte()系统调用,与系统内核的高速缓存打交道,然后高速缓存与磁盘打交道。2)直接I/O的方式
应用程序直接访问磁盘数据,而不经过系统内核数据缓冲区(比如各种数据库应用程序)3)同步访问文件方式
数据的读写都是同步操作与1)不同的是,只有当数据成功写到磁盘才返回成功给应用程序4)异步访问文件
访问数据的线程发出请求后继续处理其他的事情不必傻傻等待5)内存映射
操作系统将内存中的某一块区域与磁盘中的文件关联起来,当访问内存中的一段数据时,转换为访问文件的数据,数据是共享的Java访问磁盘文件 File 类 File并不代表一个真实存在的文件对象,可能是一个文件或者是一个包含多个文件的目录。为什么这么设计呢,因为大多数情况下,我们主要关心的是这个文件的操作,并不关心这个文件是否真的存在。比如手机通讯录的电话号码有上百个,我们关心的是有没有这个朋友的号码,但是不会去经常检测这个号码是否到底能不能打通,在真正打的时候才会去检测能不能用。就像检测一个文件是否存在就在真正要读取这个文件的时候。 FileInputStream创建时会创建一个FileDescriptor对象,该对象就是真正代表一个存在的文件对象的描述。
Java序列化 持久化对象,需要实现java.io.Serializable接口 1.当父类继承Serializable接口时,所有子类都可以被序列化 2.子类实现Serializable接口,父类没有,父类中的属性不能被序列化,数据丢失,子类中的属性可以正确序列化 3.属性是对象,该对象也要实现Serializable
网络I/O 1. TCP的状态转化( 三次握手与四次挥手) 2.Java Socket工作机制
NIO 核心:Buffer,Channel,Selector 理解BIO,NIO的思想 阻塞IO,读写阻塞线程失去CUP使用权,线程数量,线程优先级,资源竞争,同步等等问题 基于NIO的Socket请求处理:Selector监听一组Channel上的I/O状态,将数据分配到对应的数据Buffer中。一个线程来监听,监听客户端连接的请求,另外一个线程来处理所有连接的数据交互,每个连接的数据交互都不是阻塞方式。
NIO的数据访问方式比传统方式的优势 NIO两个优化方法:FileChannel.transferTo/From FileChannel.map 减少了数据从系统内核到用户空间的复制。
新闻热点
疑难解答