转换流(InputStreamReader、OutputStreamWriter)
FileReader / FileWriter 只能读写与当前环境编码兼容的文件
如果读写的文件编码与当前环境编写不兼容,使用 InputStreamReader / OutputStreamWriter
InputStreamReader 可以把字节流转换为字符流,OutputStreamWriter 可以把字符流转换为字节流,这一对流类又称为转换流
流的体系结构
- 看流的体系结构
- 创建流对象 new 字符流对象(字节,编码集)
- 字符流完成输入和输出操作
输入:以字符为单位读取到内存(缓冲区:将字节解码为字符,读到内存中)
输出:以字符为单位输出(缓冲区:将字符以指定编码集编码为字节,写到文件中)
- 释放资源 colse()
--------------------------------------------------------
InputStreamReader
InputStreamReader 是字节流通向字符流的桥梁:它使用指定的 charset 读取字节并将其解码为字符
它使用的字符集可以由名称指定或显式给定,或者可以接受平台默认的字符集。(看构造方法)
构造方法
- InputStreamReader(InputStream in) 创建一个使用默认字符集的 InputStreamReader
- InputStreamReader(InputStream in, String charsetName) 创建使用指定字符集的 InputStreamReader
成员方法
- int read() 读取单个字符
- int read(char[] cbuf) 将字符读入数组
- int read(char[] cbuf, int off, int len) 将字符读入数组的某一部分
- String getEncoding() 返回此流使用的字符编码的名称
// InputStreamReader 可以把字节流转换为字符流 public class Test01 { public static void main(String[] args) throws IOException { //1)建立流通道使用InputStreamReader流读取hehe.txt文件内容, 该文件使用GBK编码,而当前环境使用UTF-8编码, 可以通过转换流读取指定编码的文件 //1.1 先建立字节流通道 FileInputStream fis = new FileInputStream("D:\\yexiao1793\\file\\hehe.txt"); //1.2 把字节流fis以指定的GBK编码转换为字符流 InputStreamReader reader = new InputStreamReader(fis, "GBK"); // 构2 //2)以字符为单位读取文件内容 int cc = reader.read(); while (cc != -1 ){ System.out.print( (char)cc); cc = reader.read(); } //3)释放资源 reader.close(); } }
import java.io.FileInputStream; import java.io.IOException; import java.io.InputStreamReader; public class InputStreamReaderTest02 { public static void main(String[] args) throws IOException { //创建一个字符输入流对象(字节输入流 + 平台默认编码集) //必须要保证字符输入流指定的编码集和读取的文本的编码格式是一致的,才能以字符为单位读取到正确的内容 InputStreamReader isr = new InputStreamReader(new FileInputStream("day09\\a.txt")); // a.txt文件默认UTF-8编码
// a.txt文件已有内容为:我爱Java // 以字符为单位读取文本文件 /* int ch = isr.read();//以字符为单位读取文本内容到内存,将该方法的返回值char的数据类型,提升为了一个int类型 char -> int System.out.println(ch); // 25105 (作为整数读取的字符) System.out.println((char)ch); // 我
*/ /* int ch; while ((ch = isr.read()) != -1){ System.out.print((char) ch); // 我爱Java }*/ // 以字符数组为单位读取 /* int len; char[] chars = new char[4];
*/ /*
int num = isr.read(chars); System.out.println(num); // 4 System.out.println(Arrays.toString(chars)); // [我, 爱, J, a] int num2 = isr.read(chars); System.out.println(num2); // 2 System.out.println(Arrays.toString(chars)); // [v, a, J, a] (覆盖了前两位) int num3 = isr.read(chars); System.out.println(num3); // -1 (说明读完了) System.out.println(Arrays.toString(chars)); // [v, a, J, a]
*/ /* while ((len = isr.read(chars)) != -1){ System.out.print(new String(chars,0,len)); // 我爱Java } */ isr.close(); // 释放资源 } }
------------------------------------------------------
OutputStreamWriter
OutputStreamWriter 是字符流通向字节流的桥梁:可使用指定的 charset 将要写入流中的字符编码成字节
它使用的字符集可以由名称指定或显式给定,否则将接受平台默认的字符集(看构造方法)
构造方法
- OutputStreamWriter(OutputStream out) 创建使用默认字符编码的 OutputStreamWriter
- OutputStreamWriter(OutputStream out, String charsetName) 创建使用指定字符集的 OutputStreamWriter
成员方法
- void close() 关闭此流,但要先刷新它
- void flush() 刷新该流的缓冲
- String getEncoding() 返回此流使用的字符编码的名称
- void write(char[] cbuf) 写入字符数组
- void write(char[] cbuf, int off, int len) 写入字符数组的某一部分
- void write(int c) 写入单个字符
- void write(String str) 写入字符串(推荐用这个)
- void write(String str, int off, int len) 写入字符串的某一部分
//使用 OutputStreamWriter 把字符保存到指定的文件中 public class Test02 { public static void main(String[] args) throws IOException { //当前环境是UTF-8编码, 以追加的形式打开hehe.txt文件, 把字符串保存到该文件中, hehe.txt文件是GBK编码 //1.1 建立字节流通道 // FileOutputStream(String name, boolean append) append=true 表示在文件原内容上添加新内容
FileOutputStream fos = new FileOutputStream("D:\\yexiao1793\\file\\hehe.txt", true ); //创建转换流, 把当前字符以GBK编码转换为字节流 OutputStreamWriter writer = new OutputStreamWriter(fos, "GBK"); //2)通过writer转换字符流把字符串追加到hehe.txt文件中 writer.write("这是在UTF-8环境中写入的字符串"); //3)关闭 writer.close(); } }
import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStreamWriter; public class OutputStreamWriterTest { public static void main(String[] args) throws IOException { OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("day09\\e.txt")); osw.write('我'); // 写入单个字符 char[] chars = {'我','爱'}; osw.write(chars); // 写入字符数组 osw.write(chars,0,1); // 写入字符数组的一部分 '我' osw.write("我爱Java"); // 写入字符串(方便,推荐) osw.write("我爱Java",2,4); // 写入字符串的一部分 ‘Java’ osw.close(); // 关流即刷新 } }
-----------------------------------------
整合(InputStreamReader、OutputStreamWriter)
案例:把 D:\\新闻.txt 文本内容复制到 day09\\新闻.txt 文本里来
注意:InputStreamReader、OutputStreamWriter适合于 .txt 纯文本文字的复制;软件、图片、word文档这些因为无法正确(字节-字符)互转,不适用,可用这种方式:字节流 ( FileOutputStream、FileIntputStream ) - 鹿先森JIAN - 博客园 (cnblogs.com)
import java.io.*; public class CopyFileTest { public static void main(String[] args) throws IOException { InputStreamReader isr = new InputStreamReader(new FileInputStream("D:\\新闻.txt")); OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("day09\\新闻.txt")); // 方式一:逐个读写字符以完成复制 /* int ch; while ((ch = isr.read()) != -1){ osw.write(ch); }*/ // 方式二:读写字符数组以完成复制(效率相对更快) int len; char[] chars = new char[1024]; while ((len = isr.read(chars)) != -1){ osw.write(chars,0,len); } isr.close(); osw.close(); } }