这节课来讲讲转换流
在讲转换流之前了,我们先讲讲字符的编码与解码。
首先,我们知道计算机里所有数据都是以二进制的形式存储的,.java文件想要运行必须先被编译成.class字节码文件,这里我们提到了一个词,字节码,或者说字节,以往一直没机会,这次就来带大家看看字节码文件。
这些以.class为后缀名的文件就是.class文件,这些文件的内容全是字节。我们打开来看看
看不懂,对不对?我也看不懂,因为这是给计算机看的。
人看的懂的是字符,计算机能看懂的是字节,那么如何将计算机看得懂的字节变成人看得懂的字符呢?又如何将人看得懂的字符变成计算机看得懂的字节呢?
编码:
将字符转换成字节的过程叫编码,编码指按照一定的规则将字符转换成字节
解码:
将字节转换车字符的过程叫解码,解码值按照一定的规则将字节转换成字符
下面来看一段java代码
看介绍里可以看出String 的构造器可以对字节进行解码,而且可以按照指定的字符集进行解码
说一下字符集: 就是一种编码或者解码的规则,常见的字符集有: GBK,gb2312,UTF-8(这个我们以后用的最多)
String 可以解码,自然也提供了编码的方法,就是使用getBytes方法。
Demo 01:
public static void main(String[] args) throws UnsupportedEncodingException {
//先来new一个byte数组
byte[] bytes = "我爱java".getBytes("UTF-8");
String str = new String(bytes, "UTF-8");
System.out.println(str);
}
输出:
Java
注意: 如果编码字符集和解码字符集不相同的话,会出现乱码
Demo 02:
public static void main(String[] args) throws UnsupportedEncodingException {
//先来new一个byte数组
byte[] bytes = "我爱java".getBytes("UTF-8");
String str = new String(bytes, "GBK");
System.out.println(str);
}
输出:
鎴戠埍java
顺便一提:如果字符集不同的话,只有不在0-127之间的字符才会出现乱码
接下来看看乱码的第二个原因: 字节不完整
首先有一个问题,把一个字符转换成一个字节数组,那么这个字节数组的长度是多少?
Demo 03:
public static void main(String[] args) throws UnsupportedEncodingException {
byte[] bytes = "1".getBytes();
System.out.println(bytes.length); //1
bytes = "a".getBytes();
System.out.println(bytes.length); //1
bytes = "我".getBytes();
System.out.println("我".length()); //1
System.out.println(bytes.length); //3
}
结论: 0-127之间的字符转字节一个字符对应一个字节,中文的一个汉字对应3个字节,而且,一个汉字只是一个字符
Demo 04:
public static void main(String[] args) throws UnsupportedEncodingException {
byte[] bytes = "我".getBytes();
String str = new String(bytes,0,1);
System.out.println(str); //乱码
str = new String(bytes,0,3);
System.out.println(str); //正常
}
结论: 乱码的第二个原因: 字节不完整
OK,讲清楚编码和解码之后,我们再来讲讲转换流 。
转换流: 将字节流转换成字符流的流,主要作用是处理字符编码
转换流常用的两个类: InputStreamReader, OutputStreamWriter
InputStreamReader:
InputStreamReader 是字节流通向字符流的桥梁:它使用指定的 charset 读取字节并将其解码为字符。它使用的字符集可以由名称指定或显式给定,或者可以接受平台默认的字符集。
构造器:
主要用最后一个 InputSteamReader(InputStream in, String charsetName)
下面来看一个小例子:
Demo 05:
public static void main(String[] args) throws FileNotFoundException, UnsupportedEncodingException {
//这里我么有异常直接抛出,就不捕获了,方便看
// BufferedReader reader = new BufferedReader(new FileReader(new File("F:\\code\\java\\2.txt")));
//这里我们就发现了一个问题,我们在用字符流读取文件的时候,没办法指定字符集编码,这是有很大问题的
//因为编译器的默认编码可能和文件的编码不一样,这样就会造成乱码的现象
//所以我们希望能指定编码,同时又去用字符流去读取(加缓冲流是提高效率),这个时候就需要转换流
//转换流有两个: InputStreamReader, OutputStreamWriter
//这样我们就可以使用指定字符集编码的字符缓冲流来读取文件了,看起来有点麻烦,实际上了解了原理以后非常的好写,我们来重新写一遍
/**
* 第一步 new一个BufferedReader,构造器需要一个Reader类型的参数
* 第二步 由于转换流InputStreamReader是Reader的子类,所以可以把InnputStreamReader对象 传进去
* 第三步 InputStreamReader需要一个InputStream 和 一个 字符串(表示字符集编码)
*/
BufferedReader reader = new BufferedReader(
new InputStreamReader(new FileInputStream(new File("F:\\code\\java\\2.txt")), "UTF-8")
);
//这样,一个可以指定字符编码集的字符 缓冲流就构造好了,剩下的就和以前讲的一样即可
//OutputStreamWriter和InputStreamReader差不多,只不过一个读,一个写
BufferedWriter writer = new BufferedWriter(
new OutputStreamWriter(new FileOutputStream(new File("F:\\code\\java\\3.txt")),"UTF-8")
);
}