InputStreamReader 和 OutputStreamWriter 是字符和字节的桥梁,也可称之为字符转换流。
原理:字节流+编码
FileReader和FileWriter作为子类,仅作为操作字符文件的便捷类存在。当操作的字符文件,使用的是默认编码表时可以不用父类,而直接使用子类完成操作,简化代码。
一旦要指定其他编码时,不能使用子类,必须使用字符转换流。
BufferedWriter writer = new BufferedWriter( new OutputStreamWriter(new FileOutputStream(file) , "GBK"));
BufferedReader reader =new BufferedReader( new InputStreamReader(new FileInputStream(f), "GBK"));
InputStreamReader
public class InputStreamReader extends Reader
InputStreamReader 是字节流通向字符流的桥梁:它使用指定的 charset 读取字节并将其解码为字符。它使用的字符集可以由名称指定或显式给定,或者可以接受平台默认的字符集。
每次调用 InputStreamReader 中的一个 read() 方法都会导致从底层输入流读取一个或多个字节。要启用从字节到字符的有效转换,可以提前从底层流读取更多的字节,使其超过满足当前读取操作所需的字节。
-
为了达到最高效率,可以考虑在 BufferedReader 内包装 InputStreamReader。比如:
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
示例1. 读取控制台输入的内容,通过FileWriter保存
/**
* 使用 InputStream 得到数据,使用 FileWriter 写数据
* @throws IOException
*/
public static void method1() throws IOException {
// 创建输入流对象
InputStream is = System.in;
// 创建输出流对象
FileWriter fw = new FileWriter("a.txt");
// 读写数据
byte[] bys = new byte[1024];
int len;
while ((len = is.read(bys)) != -1) {
fw.write(new String(bys, 0, len));
fw.flush();
}
// 释放资源
is.close();
fw.close();
}
示例2. 通过 InputStreamReader转为 Reader
/**
* InputStream 转为 Reader 做读取数据的操作
* @throws IOException
*/
public static void method2() throws IOException {
// 创建输入流对象
InputStream is = System.in;
Reader r = new InputStreamReader(is);
// 创建输出流对象
FileWriter fw = new FileWriter("a.txt");
// 读写数据
char[] chs = new char[1024];
int len;
while ((len = r.read(chs)) != -1) {
fw.write(chs, 0, len);
fw.flush();
}
// 释放资源
is.close();
fw.close();
}
示例3. InputStreamReader 转为 BufferedReader 读取数据
/**
* InputStreamReader 转为 BufferedReader 读取数据
* @throws IOException
*/
public static void method3() throws IOException {
// 创建输入流对象
BufferedReader r = new BufferedReader(new InputStreamReader(System.in));
// 创建输出流对象
FileWriter fw = new FileWriter("a.txt");
// 读写数据
char[] chs = new char[1024];
int len;
while ((len = r.read(chs)) != -1) {
fw.write(chs, 0, len);
fw.flush();
}
// 释放资源
r.close();
fw.close();
}
测试
public static void main(String[] args) throws IOException {
method1();
method2();
method3();
}
OutputStreamWriter
public class OutputStreamWriter extends Writer
OutputStreamWriter 是字符流通向字节流的桥梁:可使用指定的 charset 将要写入流中的字符编码成字节。它使用的字符集可以由名称指定或显式给定,否则将接受平台默认的字符集。
每次调用 write() 方法都会导致在给定字符(或字符集)上调用编码转换器。在写入底层输出流之前,得到的这些字节将在缓冲区中累积。可以指定此缓冲区的大小,不过,默认的缓冲区对多数用途来说已足够大。注意,传递给 write() 方法的字符没有缓冲。
-
为了获得最高效率,可考虑将 OutputStreamWriter 包装到 BufferedWriter 中,以避免频繁调用转换器。
Writer out = new BufferedWriter(new OutputStreamWriter(System.out));
示例:把标准输出流转换成一种字符输出流
/**
* 把标准输出流转换成一种字符输出流
* @throws FileNotFoundException
* @throws IOException
*/
public static void demo() throws FileNotFoundException, IOException {
// 创建输入流
BufferedReader br = new BufferedReader(new FileReader("copy.txt"));
// 创建输出流
// OutputStream os=System.out;
Writer w = new OutputStreamWriter(System.out);// 多态,父类引用指向子类对象
String line;// 用于接收读到的数据
while ((line = br.readLine()) != null) {
w.write(line +"\n");
}
br.close();
w.close();
}
完整示例
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.UnsupportedEncodingException;
public class TransStreamDemo {
public static void main(String[] args) throws IOException {
writeCN();
readCN();
}
public static void readCN()
throws UnsupportedEncodingException, FileNotFoundException, IOException {
// InputStreamReader将字节数组使用指定的编码表解码成文字
InputStreamReader isr = new InputStreamReader(new FileInputStream("temp.txt"),
"utf-8");
char[] buff = new char[1024];
int len = isr.read(buff);
System.out.println(new String(buff, 0, len));
isr.close();
}
public static void writeCN()
throws UnsupportedEncodingException, FileNotFoundException, IOException {
// OutputStreamWriter将字符串按照指定的编码表转成字节,再使用字符流将这些字节写出去
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("temp.txt"),
"utf-8");// 本身是字符流,传入字节流
osw.write("你好");
osw.close();
}
}