本章内容:
- 基于字节、字符的I/O(相关代码)
- 字节与字符在I/O过程中的转换(StreamDecoder)
- 磁盘I/O的方式
- java中访问磁盘数据的过程
2.1.1 基于字节的I/O操作接口
基于字节的I/O操作接口输入和输出分别是lnputStream 和OutputStream,以及继承他们的类。
编程实例:用FileOutputStream类向文件中写入一个串字符,然后用FileInputStream读出写入的内容。
//FileStream.java
import java.io.*;
public class FileStream{
public static void main(String[] args) throws Exception {
FileOutputStream out = new FileOutputStream("hello.txt");
out.write("www.sina.com.cn".getBytes()); //把字符串转化为字节数组并写入到流中
out.close();
byte[] buf = new byte[1024];
File f = new File("hello.txt");
FileInputStream in = new FileInputStream(f);
int len = in.read(buf); //读取内容到字节数组中
System.out.println(new String(buf,0,len)); //String构造函数把字节数组转化为字符串,注:buf应该是字符数组(char[])、字节数组(byte[])、整型数组(int[]) 意思就是从数组中取出从下标0开始的len个元素来生成字符串对象,打印
in.close();
}
}
SocketInputStream继承自FileInputStream
操作数据的方式是可以组合使用的,如
OutputStream out = new BufferedOutputStream(new ObjectOutputStream (new FileOutputStream("aa")));
以及必须要指定流最终写到什么地方。
2.1.2 基于字符的I/O操作接口
Reader和Writer是所有字符流类的抽象基类,用于简化对字符串的输入输出编程,即用于读写文本数据。
文本文件只是二进制文件的一种特例。
为了与文本文件相区别,人们又把文本文件以外的文件称之为二进制文件。在概念上我们可以简单的认为:如果一个文件专用于存储文本字符而没有 包含字符之外的其他数据,就称之为文本文件,除此之外的文件就是二进制文件。
import java.io.*;
public class FileStream2{
public static void main(String[] args) throws Excetpion {
FileWriter out = new FileWriter("hello2.txt");
out.write("www.sina.com.cn"); //在此可以直接写入字符串,不用转化为字节数组
out.close();
char[] buf = new char[1024]; //字符数组
FileReader in = new FileReader("hello2.txt");
int len = in.read(buf); //此时的read方法可以读取一个字符或几个字符,len代表实际读取到的字符的个数。
System.out.println(new String(buf,0,1024)); //String构造函数把字符数组转化为字符串。
in.close();
}
}
2.1.3 字节与字符的转化接口
InputStream Reader 类是从字节到字符的转化桥梁,InputStream 到Reader 的过程要指定编码字符集,否则将采用操作系统默认的字符集,很可能会出现乱码问题。StreamDecoder正是完成从字节到字符的解码的实现类。也就是当你用如下方式读取一个文件时:
try{
StringBuffer str = new StringBuffer () ;
char[] buf = new char[1024];
FileReader f = new FileReader("file");
while(f.read(buf)>O) { // 如果是从文件读,改成if也可以?
str.append(buf);
str.toString();
} catch (IOException e) {
}
File Reader 类就是按照上面的工作方式读取文件的, File Reader 继承了InputStreamReader类,实际上是读取文件流,然后通过S tream Decoder 解码成char ,只不过这里的解码字符集是默认字符集。
http://blog.csdn.net/geekczt/article/details/7858780 read方法的介绍
2.2 磁盘I/O工作机制
标准访问文件的格式:
标准访问文件的方式就是当应用程序调用read 接口时,操作系统检查在内核的高速缓存中有没有需要的数据,如果己经缓存了,那么就直接从缓存中返回,如果没有,则从磁盘中读取,然后缓存在操作系统的缓存中。
写入的方式是, 用户的应用程序调用write接口将数据从用户地址空间复制到内核地址空间的缓存中。这时对用户程序来说写操作就已经完成, 至于什么时候再写到磁盘中由操作系统决定,除非显式地调用了sync 同步命令。
===
直接I/O的方式
不经过缓存,每次都直接从磁盘读取,这种访问文件的方式通常是在对数据的缓存管理由应用程序实现的数据库管理系统中。
===
同步访问文件
它与标准访问文件的方式不同的是,只有当数据被成功写到磁盘时才返回给应用程序成功的标志。只有在一些对数据安全性要求比较高的场景中才会使用,而且通常这种操作方式的硬件都是定制的。
===
异步访问文件
异步访问文件的方式就是当访问数据的钱程发出请求之后,线程会接着去处理其他事情,而不是阻塞等待,当请求的数据返回后继续处理下面的操作。这种访问文件的方式可以明显地提高应用程序的效率,但是不会改变访问文件的效率。
===
内存映射的方式
内存映射的方式是指操作系统将内存中的某一块区域与磁盘中的文件关联起来, 当要访问内存中的一段数据时,转换为访问文件的某一段数据。这种方式的目的同样是减少数据从内核空间缓存到用户空间缓存的数据复制操作,因为这两个空间的数据是共享的。
Java 访问磁盘文件
在Java 中通常的File 并不代表一个真实存在的文件对象,当你指定一个路径描述符时,它就会返回一个代表这个路径的虚拟对象, 这个可能是一个真实存在的文件或者是一个包含多个文件的目录。
何时会真正检查一个文件存不存在?就是在真正要读取这个文件时。这时将会真正创建一个关联真实存在的磁盘文件的文件描述FileDescriptor ,通过这个对象可以直接控制这个磁盘文件。