BufferedWriter与BufferedReader的使用及缓冲原理的了解
首先了解一下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; } }