首先了解一下java中文件读取的几个类:
/**
* 关于文件操作类的学习
* @see java.io.InputStream 字节流抽象类(1)
* @see FileInputStream 获得输入原始字节,主要用于图像之类的原始字节流(2)
*
* @see java.io.Reader 读取字符流的抽象类(a)
* @see BufferedReader 有缓冲,开销低(b)
* @see InputStreamReader 字节流通向字符流的桥梁,可设置编码(c)
* @see FileReader 读取字符流快捷操作(d)
*
* @since 2012/12/9
*/
其中(2)继承于(1),(b)(c) (d)继承于(a),关于输出的操作类也类似
关于BufferedWriter与BufferedReader的使用方法:
例一:
File f=new File("D:\\a.txt");
Writer r=new FileWriter(f);
BufferedWriter br=new BufferedWriter(r);
br.write("Hello");
br.flush();
br.close();
例二:
File f=new File("D:\\a.txt");
OutputStream os=new FileOutputStream(f);
Writer r=new OutputStreamWriter(os,"gbk");
BufferedWriter br=new BufferedWriter(r);
br.write("Hello");
br.flush();
br.close();
例二优点在于可以设置写入文件时字符编码,在处理乱码及编码转换时非常有用。
今天编写一个关于文件编码转化的程序,有同学遇到问题:内容不能写入文件中,当时怎么也没检查出,后来想起可能是没有调用flush() 函数并且没有close()的习惯,测试了下,确实如此。
之前以为只有BufferedWriter有缓冲,需要调用flush()函数,测试了下,
InputStreamReader,FileReader 如果不调用flush()或close()函数,都不会向文件写入数据,
那么,他们的'缓冲'与BufferedWriter 的缓冲有什么区别?(下面是JDK的解释)
OutputStreamWriter: 每次调用 write() 方法都会导致在给定字符(或字符集)上调用编码转换器。在写入底层输出流之前,得到的这些字节将在缓冲区中累积。可以指定此缓冲区的大小,不过,默认的缓冲区对多数用途来说已足够大。为了获得最高效率,可考虑将 OutputStreamWriter 包装到 BufferedWriter 中,以避免频繁调用转换器。
我粘贴下BufferedWriter类write()及flushBuffer()方法的源码并附自己的少量注释,文章中理解不到位的地方还请指出。
public void write(String s, int off, int len) throws IOException {
synchronized (lock) { //给方法加锁,确保一次只有一个线程访问
ensureOpen(); //检测stream是否打开
int b = off, t = off + len;
while (b < t) {
int d = min(nChars - nextChar, t - b); //nChars 缓冲区大小,默认8192,nextChar当前缓冲区大小,两个都是类的私有属性
s.getChars(b, b + d, cb, nextChar); //字符串追加复制到字符数组,cb缓冲区存储的字符数组
b += d;
nextChar += d;
if (nextChar >= nChars)
flushBuffer();
}
}
}
void flushBuffer() throws IOException {
synchronized (lock) {
ensureOpen();
if (nextChar == 0)
return;
out.write(cb, 0, nextChar);
nextChar = 0;
}
}