/*
* 将一个字符串数据写入到一个文本文件中。
* (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.一旦操作文本涉及到具体的指定编码表,必须使用转换流。
*/
22-IO流-30-IO流(转换流的编码解码)
最新推荐文章于 2017-11-26 23:21:00 发布