转换流
注意:JVM内部使用的编码方式为默认编码方式为系统的编码方式(当然可以自己设置),但是在IEDA中,会把默认当前运行的JVM的编码方式改成UTF-8!
而python解释器在内存中是使用的Unicode编码!
修改JVM默认编码方式!
- 在系统的环境变量中添加一个变量,名为: JAVA_TOOL_OPTIONS, 值为:-Dfile.encoding=UTF-8
- 在运行java程序的时候指定参数java -Dfile.encoding=UTF-8 Test【注意:第2种方式每次运行时都需要指定】
- 如果是web工程,可以在catalina.bat的最前面加入set JAVA_OPTS=-Dfile.encoding=UTF-8;设置了编码后使用java -help可能会出现乱码,这个时候可以使用-Duser.language=en设置一下语言
一、字符编码
-
字符编码
Character Encoding
:一套自然语言与二进制数之间的对应规则。
@@@@@@@@@@@ <-------decoded解码------------------ 1010101010
【数字,英文】
【标点符号】----------------------(编码规则)---------------------【底层二进制】
【汉字】
@@@@@@@@@@@ --------encoding编码-------------------> 1010101010
如果解码的规则和编码的规则不同,就会出现乱码的现象!
二、字符集
-
字符集
Charset
: 编码表。系统支持的所有字符的集合,包括各国国家文字、标点符号、图形符号、数字等。
常见的字符集:ASCII、GBK、Unicode、UTF-8等。
-
ASCII:(不超过1字节)**
- 基于拉丁字母、用于显示英文、包含控制字符(回车等)、显示字符
- 基本的ASCII使用7bits表示一个字符(128个字符),拓展的使用8bits(256个字符)。
-
Unicode:(统一4字节编码)**
- 标准万国码,国际标准、有三种优化编码方案:UTF-8【常用】、UTF-16、UTF-32
-
UTF-8(1-4个字节):: 一个压缩版的Unicode(空间压缩,使用1-4个字节为每个字符编码,节省空间,根据编码规则及编码头的数字可以准确判断是对应的多少字节)
- 编码规则:
- 128个US-ASCII字符:1个字节编码
- 拉丁文等:2个字节编码
- 大部分常用字(包含中文):3个字节编码
- 极少使用的Unicode辅助字符:4个字节编码
- 编码规则:
-
GB(xxx):为中文显示而设计的
- GB2312:简体中文码表。一个小于127的字符的意义与原来相同。但两个大于127的字符连在一起时,就表示一个汉字,这样大约可以组合了包含7000多个简体汉字,此外数学符号、罗马希腊的字母、日文的假名们都编进去了,连在ASCII里本来就有的数字、标点、字母都统统重新编了两个字节长的编码,这就是常说的"全角"字符,而原来在127号以下的那些就叫"半角"字符了。
- GBK: 最常用的(一个汉字两个字节),扩展了GB2312,双字节编码方法,共收录了21003个汉字,完全兼容GB2312标准,同时支持繁体汉字以及日韩汉字等
- GB18030: 最新的中文码表,收录汉字70244个,采用多字节编码,每个字可以由1个、2个或4个字节组成。支持中国国内少数民族的文字,同时支持繁体汉字以及日韩汉字等。
ISO-8859-1:拉丁码表、Latin-1、欧洲使用、一个字节编码,兼容ASCII
三、InputStreamReader
转换流
java.io.InputStreamReader
是Reader
的子类、字节流 到 字符流 的桥梁,读取字节,使用指定的字符集将其解码为字符。可指定名称、可接受系统默认编码方式。
1.构造方法(省略public)
InputStreamReader(InputStream in)
: 创建一个使用默认字符集的字符流,使用系统的编码方式。-
InputStreamReader(InputStream in, String charsetName)
:创建一个指定字符集的字符流。- 继承自父类的方法:int read()、int read(char[] cbuf)、void close()
InputStream抽象接口一般肯定是使用FileInputStream!
- 使用步骤:
1. 创建InputStreamReader对象,构造方法中传递字节输入流和指定的编码表名称
2. 使用InputStreamReader对象中的方法read读取文件
3. 释放资源
- 注意事项:构造方法中指定的编码表名称要和文件的编码相同,否则会发生乱码
案例:使用指定字符集读取文件!
BufferedReader
结合InputStreamReader
再结合FileInputStream
使用
/**@指定字符级
* BufferedReader(需要传入Reader -- InputStreamReader)
* InputStreamReader是Reader的子类,
* InputStreamReader(需要传入InputStream -- FileInputStream)
*/
InputStreamReader isr = new InputStreamReader(new FileInputStream("F:\\test\\GBK.txt"), "GBK");
BufferedReader br = new BufferedReader(isr);
System.out.println(br.readLine());
br.close();
isr.close();
// 我是GBK编码的,哈哈,必须的使用GBK编码方式才能读出来知道不!
四、OutputStreamWriter
转换流
java.io.OutputStreamWriter
,Writer子类,字符流到字节流的桥梁,可使用操作系统默认字符集将字符编码为字节。字符集也可以由名称指定。
1.构造方法(省略public)
-
OutputStreamWriter(OutputStream out)
: 创建一个使用默认字符集的字符流 -
OutputStreamWriter(OutputStream out, String charsetName)
: 创建一个指定字符集的字符流- 继承父类的方法:write(int c)、write(char[] cbuf)、write(char[] cbuf, int off, int len)、write(String str)、write(String str, int off, int len)、flush()、close()
-使用步骤:- 创建OutputStreamWriter对象,构造方法中传递字节输出流和指定的编码表名称
- 使用OutputStreamWriter对象中的方法write,把字符转换为字节存储缓冲区中(编码)
- 使用OutputStreamWriter对象中的方法flush,把内存缓冲区中的字节刷新到文件中(使用字节流写字节的过程)
- 释放资源
使用指定编码写出
- 继承父类的方法:write(int c)、write(char[] cbuf)、write(char[] cbuf, int off, int len)、write(String str)、write(String str, int off, int len)、flush()、close()
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("F:\\test\\UTF-8.txt"), "UTF-8");
BufferedWriter bw = new BufferedWriter(osw);
osw.write("UTF-8编码方式");
osw.close();
osw.close();
转换流是字节与字符间的桥梁
将GBK编码的文件转换为UTF-8的文本文件
// GBK编码内容:我是GBK编码的,哈哈,必须得使用GBK编码方式才能读出来知道不!
String line;
InputStreamReader isr = new InputStreamReader(new FileInputStream("F:\\test\\GBK.txt"), "GBK");
BufferedReader br = new BufferedReader(isr);
line = br.readLine();
br.close();
isr.close();
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("F:\\test\\UTF-8.txt"), "UTF-8");
BufferedWriter bw = new BufferedWriter(osw);
osw.write(line);
osw.close();
osw.close();
IDEA中,JVM运行使用的编码方式!
// GBK编码内容: 我
String line;
InputStreamReader isr = new InputStreamReader(new FileInputStream("F:\\test\\GBK.txt"), "GBK");
BufferedReader br = new BufferedReader(isr);
line = br.readLine();
br.close();
isr.close();
System.out.println("内容:‘" + line + "’ 编码方式GBK ,外存中大小2字节,JVM中 " + line.getBytes().length + "字节");
// UTF-8编码内容:我
InputStreamReader isr2 = new InputStreamReader(new FileInputStream("F:\\test\\UTF-8.txt"), "UTF-8");
BufferedReader br2 = new BufferedReader(isr2);
line = br2.readLine();
br2.close();
isr2.close();
System.out.println("内容:‘" + line + "’ 编码方式UTF-8,外存中大小3字节,JVM中 " + line.getBytes().length + "字节");
/** IDEA中
* 内容:‘我’ 编码方式GBK ,外存中大小2字节,JVM中 3字节
* 内容:‘我’ 编码方式UTF-8,外存中大小3字节,JVM中 3字节
*/
中国境内的win环境下
// GBK: One Character(我)
String line;
InputStreamReader isr = new InputStreamReader(new FileInputStream("GBK.txt"), "GBK");
BufferedReader br = new BufferedReader(isr);
line = br.readLine();
br.close();
isr.close();
System.out.println("content:" + line + "GBK OutMemory 2; In JVM: " + line.getBytes().length + " bytes");
//GBK: One Character(我)
InputStreamReader isr2 = new InputStreamReader(new FileInputStream("UTF-8.txt"), "UTF-8");
BufferedReader br2 = new BufferedReader(isr2);
line = br2.readLine();
br2.close();
isr2.close();
System.out.println("content:" + line + "UTF-8 OutMemory 3; In JVM: " + line.getBytes().length + " bytes");
/*
content:我GBK OutMemory 2; In JVM: 2 bytes
content:我UTF-8 OutMemory 3; In JVM: 2 bytes
*/