来自书籍:深入JAVA WEB技术内幕
1.Java I/O类库的基本架构
java的I/O操作类在包java.io下,大概有将近80多个类,大概可以分下面4组:
- 基于字节操作的I/O接口: InputStream和OutPutStream
- 基于字符操作的I/O接口:Writer和Reader
- 基于磁盘操作的I/O接口:File
- 基于网络操作的I/O接口:Socket
前两组主要是传输数据的数据格式,后两组主要是传输数据的方式。
1.1基于字节操作的I/O接口 InputStream 和OutPutStream
InputStream接口常用方法 :
int read();
int available();
int read(byte[] b) ;
int read(byte[] b,int off,int l);
OutputStream接口常用方法:
close();
flush();
writer(byte[] b) ;
writer(byte[] b,int off,int l);
1.2基于字符的I/O操作的接口:Writer和Reader.
I/O操作的最小存储单元是字节,但是由于我们程序中通常操作的是字符,所以提供了操作字符的I/O方法。
Writer接口常用方法:
writer(byte[] b);
writer(byte[] b,int setOff,int l);
writer(String s,int setOff,int l);
writer(int i);
flush();
close();
Reader接口常用方法:
int read();
int read(byte[] b);
int read(byte[] b,int setOff,int l);
void close();
1.3字节与字符的转化接口
数据持久化或网络传输都是以字节进行的,所以要懂得字节与字符之间相互转换。
InputStreamReader类
private final StreamDecord sd; // 字符流和字节流的转换器.
InputStreamReader 继承了Reader类, 重写了read() 和read(char[] c,int off,int l) 方法, 调用了sd的read() 和 read(char[] c,int off,int l) 方法。
OutputStreamWriter 继承了Writer , 重写了writer()等方法。
点进去可以看到 StreamDecord 源码
点进去可以看看 对应的使用和理解
简单理解为: InputStreamReader 和outputSteamWriter 是java提供的 字节和字符的转换器,
比如:
文件 File file = new File(path);
要对其操作 只能通过字节流 FileInputStream进行操作。
如果想要通过字符流 来操作, 就会用到转换器,FileReader(继承inputStreamReader) 或者InputStreamReader
那么我是不是可以理解为 要对系统中文件操作, 就一定先要以字节流的形式获取呢?
1.4磁盘I/O的工作机制
几种访问文件的方式:
1.标准的访问/写入方式:
访问:从物理磁盘复制数据至内核地址空间, 再由内核地址空间复制数据到用户地址空间
内核地址空间会有相对应的缓存-高速缓存,如果内核地址空间有缓存所需要的数据时,就直接从内核地址空间复制到用户地址空间。
写入:用户的应用程序调用write()接口将数据从用户地址空间复制到内核地址空间,用户程序所做的就到此,
至于系统什么时候将内核地址空间的数据 写进磁盘中,那是系统决定的,除非显示的调用 sync同步命令。
2.直接的I/O方式
直接I/O访问方式, 就是越过了内核地址空间,直接从应用程序访问磁盘数据, 这样我们就少了一次数据的复制(从内核地址空间到用户地址空间)。
当数据管理系统明确知道哪些数据需要缓存, 哪些数据应该失效,还可以对一些热点数据进行预加载,提前将热点数据加载到内存中,可以加快数据访问效率。
(操作系统只会简单的缓存最近一次从磁盘读取的数据)
这样直接的I/O访问方式肯定是有负面影响的,如果每次都直接从磁盘里读取数据的话,加载会很慢。
3.内存映射方式
操作系统内存某一块区域与磁盘的文件关联起来,当访问某一块区域时候,转换为访问文件的某部分数据。 这样,同样减少了从磁盘复制数据到内核地址空间这一步。
1.5 JAVA访问磁盘文件
卡!!!!!!!!!!!!!