缓存是I/O的一种性能优化。缓存流为I/O流增加了内存缓存区。有了缓存区,使得在流上执行skip()、 mark() 和 reset() 方法都成为可能。
1.BufferedInputStream与BufferedOutputStream类
BufferedInputStream类可以对所有InputStream类进行带缓存区的包装以达到性能的优化。BufferedInputStream类有两个构造方法:
- BufferedInputStream(InputStream in)
- BufferedInputStream(InputStream in, int size)
第一种形式的构造方法创建了一个带有32个字节的缓存流;第二种形式的构造方法按指定的大小来创建缓存区。一个最优的缓存区的大小,取决于它所在的操作系统、可用的内存空间以及机器配置。从构造方法可以看出,BufferedInputStream对象位于InputStream类对象之前,下图描述了字节数据读取文件的过程:
使用BufferedOutputStream输出信息和利用OutputStream输出信息完全一样,只不过BufferedOutputStream有一个flush()方法用来将缓存区的数据强制输出完。BufferedOutputStream类也有两个构造方法:
- BufferedOutputStream(OutputStream in)
- BufferedOutputStream(OutputStream in, int size)
第一种构造方法创建一个有32个字节的缓存区,第二种构造方法以指定的大小来创建缓存区。
flush()方法就是用于即使在缓存区没有满的情况下,也将缓存区的内容强制写入到外设,习惯上称这个过程为刷新。flush()方法只对使用缓存区的OutputStream类的子类有效。当调用close()方法时,系统在关闭流之前,也会将缓存区中的信息刷新到新的磁盘文件中。
2.BufferedReader与BufferedWriter类
BufferedReader类与BufferedWriter类分别继承Reader类与Writer类。这两个类同样具有内部缓存机制,并可以以行为单位进行输入/输出。
根据BufferedReader类的特点,总结出下面字符数据读取文件的过程:
BufferedReader类常用的方法如下:
方法 | 说明 |
---|---|
read() | 读取单个字符 |
readLine() | 读取一个文本行,并将其返回为字符串。若无数据可读,则返回null。BufferedWriter类中的方法都返回void |
write(String s, int off, int len) | 写入字符串的某一部分 |
flush() | 刷新该流的缓存 |
newLine() | 写入一个行分隔符 |
在使用BufferedWriter类的Write()方法时,数据并没有立刻被写入输出流,而是首先进入缓存区中,如果想立刻将缓存区中的数据写入输出流,一定要调用flush()方法。
public class Student{ //创建类
public static void main(String args[]){ //主方法
String content[] = {"好久不见","最近好吗","常联系"}; //定义字符串数组
File file = new File("world.txt"); //创建文件对象
try{
FileWriter fw = new FileWriter(file); //创建FileWriter类对象
BufferedWriter bufw = new BufferedWriter(fw); //创建BufferedWriter类对象
for(int k=0;k<content.lenth;k++){ //循环遍历数组
bufw.write(content[k]); //将字符串数组中的元素写入到磁盘文件中
bufw.newLine(); //将数组中的单个元素以单行的形式写入文件
}
bufw.close(); //将BufferedWriter流关闭
fw.close(); //将FileWriter流关闭
}catch(Exception e){
e.printStackTrace(); //处理异常
}
try{
FileReader fr = new FileReader(file); //创建FileReader类对象
BufferedReader bufr = new BUfferedReader(fr); //创建BufferedReader类对象
String s = null; //创建字符串变量
int i = 0; //生命int型变量
//如果文件的文本行数不为null,则进入循环
while((s = bufr.readLine()) != null){
i++; //将变量做自增运算
System.out.println("第"+ i + "行:" + s); //输出文件数据
}
bufr.close(); //将FileReader流关闭
fr.close(); //将FileReader流关闭
}catch(Exception e) {
e.printStackTrace(); //处理异常
}
}
}
3.数据输入/输出流
数据输入/输出流(DataInputStream类与DataOutputStream类)允许应用程序以与机器无关的方式从底层输入流中读取基本Java数据类型。也就是说,当读取一个数据时,不必再关心这个数值应当是哪种字节。
DataInputStream类与DataOutputStream类的构造方法如下:
- DataInputStream(InputStream in):使用指定的基础InputStream创建一个DataInputStream。
- DataOutputStream(OutputStream out):创建一个新的数据输出流,将数据写入指定基础输出流。
DataOutputStream类提供了如下3种写入字符串的方法。
- writeBytes(String s)
- writeChars(String s)
- writeUTF(String s)
由于Java中的字符是Unicode编码,是双字节的,writeBytes只是将字符串中的每一个字符的低字节内容写入目标设备中;而writeChars将字符串中的每一个字符的两个字节的内容都写到目标设备中;writeUTF将字符串按照UTF编码后的字节长度写入目标设备,然后才是每一个字节的UTF编码。
DataInputStream类只提供了一个readUTF()方法返回字符串。这是因为要在一个连续的字节流读取一个字符串,如果没有特殊的标记作为一个字符串的结尾,并且不知道这个字符串的长度,就无法指导读取到什么位置才是这个字符串的结束。DataOutputStream类中只有writeUTF()方法向目标设备中写入字符串的长度,所以也能准确地读回写入字符串。
public class Example_01{
public static void main(String[] args){
try{
FileOutputStream fs = new FileOutputStream("world.txt"); //创建FileOutputStream对象
DataOutputStream ds = new DataOutputStream(fs); //创建DataOutputStream对象
ds.writeUTF("使用writeUTF()方法写入数据;"); //写入磁盘文件数据
ds.writeChars("使用writeChars()方法写入数据;");
ds.writeBytes("使用writeBytes()方法写入数据;");
ds.close(); //将流关闭
FileInputStream fis = new FileInputStream("word.txt"); //创建FileInputStream对象
DataInputStream dis = new DataInputStream("fis"); //创建DataInputStream对象
System.out.print(dis.readUTF()); //将文件数据输出
}catch(Exception e){
e.printStackTrace() //输出异常信息
}
}
}