22-IO流-30-IO流(转换流的编码解码)

来源:互联网 发布:天津网络大学 编辑:程序博客网 时间:2024/05/20 11:25
/* * 将一个字符串数据写入到一个文本文件中。 * (1)明确源和目的:源是字符串,不需要流去关联它,目的需要流关联:OutStream,Writer * (2)是否为纯文本:源不需要流关联,只考虑目的,是纯文本,那么用Writer * (3)明确具体设备:源不管,目的是硬盘,那用File *  * FileWriter fw = new FileWriter("a.txt"); * fw.write("你好"); *//* * 编码表小常识: * (1)电脑操作系统是什么版本,就用什么编码表,如简体中文版,那就用GBK表 *  * (2)对于字符类型数据,java均用Unicode码表解析,但是字符串,java用的是当前电脑的默认码表GBK *  * (3)为方便各国文字编码,通常用2字节表示一个字符,但是对于'a'只需要一个字节,那用2字节如何表示?Unicode会在第一个字节位置 * 用8个0表示,再用第二个字节表示字符a,由此发现Unicode码表较浪费空间 *  * 所以导致同一个文字在不同码表中的查询结果也不同 *  * (4)后来有了UTF-8码表,该码表特点是先判断当前字符占几个字节,占1个就用1个字节存,占2个就用2个字节存,占3个就用3个字节存, * 该码表给每一个字节头部加了一个编码头,从而出现2个字节装不下的情况。 *  *//** * 【新需求】将一个字符串按照指定编码表写入文本文件中。 */package demo;import java.io.FileInputStream;import java.io.FileOutputStream;import java.io.FileReader;import java.io.FileWriter;import java.io.IOException;import java.io.InputStreamReader;import java.io.OutputStreamWriter;public class Demo {public static void main(String[] args) throws IOException {readText_2();}public static void writeText_1() throws IOException {FileWriter fw = new FileWriter("gbk_1.txt");//FileWriter就用默认编码表(当前系统是什么就用什么),不好改变fw.write("你好");fw.close();//至此,在当前目录下新建gbk_1文本文件,其内容为:你好,大小为4字节(一个汉字=2字节)}public static void writeText_2() throws IOException {/* * 对于新需求,发现FileWriter有局限,即编码表已经指定,查找API,发现转换流OutputStreamWriter有如下描述: * 可使用指定的 charset 将要写入流中的字符编码成字节 * 也就是说,该转换流可以指定任意编码表进行编码 */OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("gbk_2.txt"));//默认编码表osw.write("你好");osw.close();//这三行代码运行效果同writeText_1/* * FileOutpuStream是字节流和文件相关联 * 转换流OutputStreamWriter的构造方法摘要中: * (1)OutputStreamWriter(OutputStream out):按照默认编码表(当前系统是什么,就用什么编码表)进行编码 * (2)OutputStreamWriter(OutputStream out, String charsetName) :直接指定编码表名字即可,如GBK等 * 第二个构造函数需要抛出异常:UnsupportedEncodingException,如果传进去一个“WC”,不支持,直接抛出异常 */OutputStreamWriter osw1 = new OutputStreamWriter(new FileOutputStream("gbk_3.txt"),"GBK");//FileOutputStream父类是OutputStream,所以这里传进去相当于多态。osw1.write("你好");osw1.close();//这三行代码运行效果同writeText_1/* * OutputStreamWriter osw1 = new OutputStreamWriter(new FileOutputStream("gbk_3.txt"),"GBK"); * FileWriter fw = new FileWriter("gbk_1.txt"); *  * 这两句代码的功能相同。 * FileWriter:其实就是转换流指定了本机默认码表的体现,而且这个转换流的子类对象,便于且只能操作文本文件(File)。 * 简单说:操作文件的字节流+本机默认的编码表 * 其局限就是:无法指定任意编码表,编码表是固定的。但这也是按照默认码表来操作文件的便捷类。 *  * 如果需要指定编码表,那就必须用转换流完成。 */}public static void writeText_3() throws IOException{//指定UTF-8码表进行编码OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("u8_1.txt"),"UTF-8");osw.write("你好");osw.close();/* * 运行结果,在当前目录下生成一个名为u8_1的文本文件,其内容是:你好,大小是6字节而不是4字节。 * 因为在UTF-8码表中,一个汉字=3字节,而GBK是一个汉字=2字节。 */} public static void readText_1() throws IOException {FileReader fr = new FileReader("gbk_1.txt");char[] buf = new char[1024];int len = fr.read(buf);String str = new String(buf,0,len);System.out.println(str);fr.close();//成功读取gbk_1中的内容你好到控制台上,但是FileReader码表已经固定,是GBK,所以这几行代码读不了u8_1.txt}public static void readText_2() throws IOException {//读取指定编码表的文本文件,FileReader已经不管用,需要转换流来完成InputStreamReader isr = new InputStreamReader(new FileInputStream("u8_1.txt"),"UTF-8");//FileInputStream是用字节流读取文本文件,然后传给转换流InputStreamReader,因为转换流可以指定任意码表进行解析char[] buf = new char[1024];int len = isr.read(buf);String str = new String(buf,0,len);System.out.println(str);isr.close();//成功读取用UTF-8编码的文本文件u8_1中内容:你好//【注意】只要读取出看不懂的乱码,八成是编码表错误。}}/** * 重新审视新需求: * 既然需求中已经明确了指定编码表的动作,那就不可以用FileWriter,因为FileWriter * 内部是使用默认的本地码表,只能使用其父类转换流OutputStreamWriter,该转换流 * 接收一个字节输出流对象,既然是操作文件,那么该对象应该是FileOutputStream *  * 代码如下: * OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("u8_1.txt"),"UTF-8")); *  * 高效: * BufferedWriter bufw = new BufferedWriter(new OutputStreamWriter(new FileOutputStrem("u8_1.txt"),"UTF-8")); *//** * 什么时候使用转换流? * 1.源或者目的对应的设备是字节流,但是操作的却是文本数据,可以使用转换作为桥梁, * 提高对文本操作的便捷。 * 2.一旦操作文本涉及到具体的指定编码表,必须使用转换流。 */

0 0
原创粉丝点击