49.字符编码与转换流

转换流

注意:JVM内部使用的编码方式为默认编码方式为系统的编码方式(当然可以自己设置),但是在IEDA中,会把默认当前运行的JVM的编码方式改成UTF-8!
而python解释器在内存中是使用的Unicode编码!

修改JVM默认编码方式!

  1. 在系统的环境变量中添加一个变量,名为: JAVA_TOOL_OPTIONS, 值为:-Dfile.encoding=UTF-8
  2. 在运行java程序的时候指定参数java -Dfile.encoding=UTF-8 Test【注意:第2种方式每次运行时都需要指定
  3. 如果是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等。

字符集与编码规则.png
  • 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.InputStreamReaderReader的子类、字节流字符流 的桥梁,读取字节,使用指定的字符集将其解码为字符。可指定名称、可接受系统默认编码方式。

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()
      -使用步骤:
      1. 创建OutputStreamWriter对象,构造方法中传递字节输出流和指定的编码表名称
      2. 使用OutputStreamWriter对象中的方法write,把字符转换为字节存储缓冲区中(编码)
      3. 使用OutputStreamWriter对象中的方法flush,把内存缓冲区中的字节刷新到文件中(使用字节流写字节的过程)
      4. 释放资源
        使用指定编码写出
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();

转换流是字节与字符间的桥梁

转换流是字节与字符间的桥梁.png

将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
*/
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,402评论 6 499
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,377评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,483评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,165评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,176评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,146评论 1 297
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,032评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,896评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,311评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,536评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,696评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,413评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,008评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,659评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,815评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,698评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,592评论 2 353

推荐阅读更多精彩内容