字符流的出现为了方便操作字符;
更重要的是加入了编码转换;
通过子类转换流来完成;
InputStreamReadme
OutputStreamWriter
在两个对象进行构造的时候可以加入字符集;
编码表的由来
计算机只能识别二进制数据,早期由来是电信号;
为了方便应用计算机,让它可以识别各个国家的文字;
就将各个国家的文字用数字来表示,并一一对应,形成一张表;
这就是编码表;
常见的编码表:
ASCII:美国标准信息交换码,用一个字节的7位就可以表示;
ISO8859-1:拉丁码表,欧洲码表,用一个字节的8位表示;
GB2312:中国的中文编码表;
GBK:中国的中文编码表升级,融合了更多的中文文字字符号;
Unicode:攻击标准码,融合了多种文字;
所有文字都用两个字节来表示,Java语言使用的就是unicode;
UTF-8:最多用三个字节来表示一个字符;
......
将“你好”的文字以两种编码表的方式存放到指定的文件中
package com.javaxl.io.charset; import java.io.*; /** * @author 小李飞刀 * @site www.javaxl.com * @company * @create 2019-06-16 19:50 */ public class EncodeStreamDemo { public static void main(String[] args) throws IOException { write(); read(); } public static void write() throws IOException { OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("C:\\encodeStreamDemo.txt"),"UTF-8"); osw.write("你好"); osw.close(); } public static void read() throws IOException { InputStreamReader isr = new InputStreamReader(new FileInputStream("C:\\encodeStreamDemo.txt"),"UTF-8"); char[] cbuf = new char[16]; int len = isr.read(cbuf); System.out.println(new String(cbuf,0,len)); isr.close(); } }
注意:
写入流和读取流字符编码一致的话,那么不会出现乱码问题;
如果写入流编码是UTF-8,读取流解码参照的码表是GBK,那么会得到看不懂的三个字符;
如果写入流编码是GBK,读取流解码参照的码表UTF-8,那么会得到看不懂的两个字符;
原因参考下面截图
图解文件读取字符乱码
编码:字符串变成字节数组;
解码:字节数组变成字符串;
String-->byte[]:str.getBytes(charsetName);
Byte[]-->String:new String(byte[],charsetName);
package com.javaxl.io.charset;
import java.io.UnsupportedEncodingException;
import java.util.Arrays;
/**
* @author 小李飞刀
* @site www.javaxl.com
* @company
* @create 2019-06-16 20:06
*
* jsp乱码问题
*/
public class JspEncodeDemo {
public static void main(String[] args) throws UnsupportedEncodingException {
String s = "你好";
byte[] b1 = s.getBytes("GBK");
System.out.println(Arrays.toString(b1));
String s1 = new String(b1, "ISO8859-1");
System.out.println("s1=" + s1);
byte[] b2 = s1.getBytes("ISO8859-1");
System.out.println(Arrays.toString(b2));
String s2 = new String(b2, "GBK");
System.out.println("s2=" + s2);
}
}
UTF-8与GBK相互编码的问题
package com.javaxl.io.charset;
import java.io.UnsupportedEncodingException;
import java.util.Arrays;
/**
* @author 小李飞刀
* @site www.javaxl.com
* @company
* @create 2019-06-16 20:06
*
* UTF-8与GBK相互编码的问题
*/
public class EncodeExceptionDemo {
public static void main(String[] args) throws UnsupportedEncodingException {
String s = "你好";
byte[] b1 = s.getBytes("GBK");
System.out.println(Arrays.toString(b1));
String s1 = new String(b1, "UTF-8");
System.out.println("s1=" + s1);
byte[] b2 = s1.getBytes("UTF-8");
System.out.println(Arrays.toString(b2));
String s2 = new String(b2, "GBK");
System.out.println("s2=" + s2);
}
}
注意:GBK与UTF-8相互编码解码会有问题,因为都识别中文,一个对应两个字节,一个对应三个字节;所以编码解码编码解码最终不能得到最初的字符串;
现象描述:
在普通记事本中输入“你好”二字,保存后打开,显示“你好”二字,这不会出现任何问题;
但是删掉“你好”二字,写入“联通”二字,保存后打开,会发现“联通”二字,不会出现,普通记事本中出现了乱码;
原因:
package com.javaxl.io.charset; import java.io.UnsupportedEncodingException; /** * @author 小李飞刀 * @site www.javaxl.com * @company * @create 2019-06-16 20:15 */ public class LianTongDemo { public static void main(String[] args) throws UnsupportedEncodingException { String s = "联通"; byte[] bytes = s.getBytes("GBK"); for (byte b : bytes) { System.out.println(Integer.toBinaryString(b & 255)); } } }
“联通”二字用GBK进行编码后,所得到的二进制,正好对应着UTF-8中的两个字节的解码方式(UTF-8最多用三个字节表示一个汉字,这里正好符合两个字节表示一个汉字的规律),
但是GBK所编码出来的二进制(两个字节),又在UTF-8中找不到对应的汉字,所以出现了乱码;
备案号:湘ICP备19000029号
Copyright © 2018-2019 javaxl晓码阁 版权所有