Java中的编码问题:接收、转码、输出

原创 2017年06月11日 00:35:04

1 常见的问题

在从网络获取数据后,在JVM中进行解析运算时,最后输出的过程中都会遇到不同的编码转码问题。本文涉及的主要有如下问题:

  • Java发送HTTP请求后,接到服务器传回数据stream(如html文本),在Console中显示中文乱码。
  • Java将获取的数据输出为本地文件,在本地打开后中文显示乱码。

2 JVM从外部获得数据后的编码问题

2.1 关键理解

  • Java或者JVM、内存都是采用Unicode进行编码,一个char占2个bytes。
  • 在接收到IO字节流、向IO输出字节流的时候,都是以Unicode为桥梁,IO输入会先转为Unicode,输出会从Unicode转为相应编码。
  • 从服务器获取的数据,如一个html网页,meta数据中如果标记采用GBK编码,那么接收的IO byte[]中就是采用相应的编码方式表示中文的。
  • 所以从外部接收的数据,想让JVM自身能正确存储、显示,实质就是先正确利用发送方的编码方式来解读bytes,存为Unicode的char stream过程。

2.2 示例

通过这个过程了解Java在接受IO数据时的转码。GBK-> Unicode->UTF-8

//有一个URLConnection
URL realUrl = new URL("http://...");
URLConnection connection = realUrl.openConnection();
connection.setRequestProperty("accept", "*/*");
            connection.setRequestProperty("connection", "Keep-Alive");
            connection.setRequestProperty("user-agent",
                    "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
//建立连接
connection.connect();
//假设服务器返回的html网页中meta标签charset="GBK"
in = new BufferedReader(new InputStreamReader(
            connection.getInputStream(),
            "gbk")); //第二个参数标记用什么编码解读byte stream
String result = "";
String line;
while ((line = in.readLine()) != null) {
    result += line;
}
// 此时result在内存是以Unicode形式编码存储,而且解读正确
// 最终result中的中文可以被正常打印再终端,在打印的时候,会根据环境设置,如JVM设置以UTF-8编码输出,则会将Unicode的char stream转为UTF-8的字符串再输出到终端。
System.out.println(result);

3 JVM输出到文件的编码

3.1 关键理解

  • Java、JVM、内存中存储的char stream是以Unicode编码的,再次强调Unicode的桥梁作用。
  • 所以一串数据如果已经被正确解读为Unicode的char stream(此时console可以正常print)存储在内存中,也就和原来是什么编码无关了,输出时的主要工作是建立需求编码对应的Writer和对应编码的内容,char stream,用正确的Writer和正确的数据就能输出正确的文件。
  • 简单来说,一个String输出到文件过程,就是将Unicode的char stream转换为对应编码的char stream在输出的过程。

3.2 示例

// 通过Charset类可以查看JVM本地的编码格式,就是默认输出时的编码
System.out.println(Charset.defaultCharset());
// 建立输出流,假设要输出服务器返回的网页信息
File file = new File("C:/Users/xxx/Documents/todo/Feedback.html");
BufferedWriter bf = new BufferedWriter(new OutputStreamWriter(
        new FileOutputStream(file),
        "GBK") // 第二个参数说明了这个writer的编码方式,否则按照默认
        );
// 获取正确编码的char stream并输出
String sr = "xxxx";
String str = new String(sr.getBytes("GBK"), "GBK");
    // 第一个参数表示用GBK的方式将Unicode char stream转为用GBK编码的byte[]
    // 有了byte[]序列还需要转为char stream,第二个参数表示生成一个GBK的String,用于输出,这才是正常的。
    // 不指定会用默认的编码方式(这里是UTF-8对字节数组再编码),输出还是UTF-8,且中文乱码。

4 JVM输出到命令提示符的编码

如果正常编译运行,用cmd通过java -jar的方式运行jar包是可以正常输出的。但如果在运行前,使用CHCP 65001这样的命令来切换显示编码到UTF-8,就会发现中文显示乱码。所以还是理解,如果以默认的方式存储的String或者自己解码的String都是以Unicode存在JVM中,在输出的时候,因为系统环境是GBK的,所以会自动以GBK的形式输出。
但如果String本身有自己的指定编码方式,那么就会直接输出其对应的byte stream到目标环境中。如从网络上获取的一段用UTF-8编码的HTTP返回的json串,在指定UTF-8的Eclipse环境中调试,console中的中文会显示正常。但是如果直接做成jar包在windows的cmd中运行,由于其环境是GBK的,就会显示乱码。解决方式如2.2实例,其中修改解码方式为:

//建立连接
connection.connect();
//用utf-8的方式解读字节流
in = new BufferedReader(new InputStreamReader(
            connection.getInputStream(),
            "utf-8"));

正确存为内存的Unicode后,在cmd中的普通输出自然就正常了。

5 参考资料

为了简洁,其他内容可以看一些参考资料。

版权声明:本文为博主原创文章,未经博主允许不得转载。

JAVA编码(中文转码)问题总结

本章主要分析Java编码和解码的原理,以及中文转码
  • tangyanbo1110
  • tangyanbo1110
  • 2014年11月08日 16:59
  • 3224

java的字符转码;eclipse设置UTF-8

第一部分: myeclipse如何设置utf-8第二部分: 来源:http://www.zhihu.com/question/20361462什么是字符编码? 来源:http://zh.wiki...
  • fengfeng043
  • fengfeng043
  • 2015年04月17日 15:40
  • 1328

JAVA编码转换的详细过程理解—>浏览器和服务器的接收和发送数据的编码

一、JAVA编码转换的详细过程 我们常见的JAVA程序包括以下类别:   *直接在console上运行的类(包括可视化界面的类)   *JSP代码类(注:JSP是Servlets类的变型)  ...
  • congcongsuiyue
  • congcongsuiyue
  • 2014年10月16日 10:59
  • 2527

JS和JAVA中常用的编码转码函数

js中escape,encodeURI,encodeURIComponent函数和unescape,decodeURI和decodeURIComponent函数的功能 1.escape方法对Stri...
  • fmwind
  • fmwind
  • 2014年09月04日 17:17
  • 1732

Python编码格式说明及转码函数encode和decode的使用

字符串编码常用类型:utf-8,gb2312,cp936,gbk等。 python中,我们使用decode()和encode()来进行解码和编码 在python中,使用unicode类型作为编码的...
  • mfcing
  • mfcing
  • 2015年01月23日 17:47
  • 18881

Java 正确的做字符串编码转换

Java 正确的做字符串编码转换 字符串的内部表示? 字符串在java中统一用unicode表示( 即utf-16 LE) , 对于 String s = "你好哦!"; 如果源码文件是GB...
  • H12KJGJ
  • H12KJGJ
  • 2017年06月20日 12:55
  • 3969

第六周作业1——利用哈夫曼编码英文字母表

哈夫曼编码的具体步骤归纳如下:        ① 概率统计(如对一幅图像,或m幅同种类型图像作灰度信号统计),得到n个不同概率的信息符号。        ② 将n个信源信息符号的n个概率,...
  • u012088516
  • u012088516
  • 2014年04月18日 13:56
  • 565

java实现url编码与中文的互相转换

通过URLtoUTF8类中的toUtf8String和unescape两个方法,分别实现汉字转成URL编码和URL编码转成汉字的功能。在main()方法更改参数即可,完成测试转换。 package t...
  • u012364841
  • u012364841
  • 2014年12月16日 19:16
  • 2159

java转换流、乱码之编码与解码

package com.bjsxt.io.convert; import java.io.UnsupportedEncodingException; public class ConverDemo...
  • damotiansheng
  • damotiansheng
  • 2015年05月19日 10:05
  • 5546

Android Java中将unicode的汉字码转换成utf-8格式的汉字

最近项目中跟后台的交互莫名其妙的String类型的全部都是”乱码”了。比如网络请求给后台post传递的参数中有一个String类型的参数,结果到了后台哪里接收到的就是”乱码”了,同样的,后台给返回回来...
  • qq_34471736
  • qq_34471736
  • 2017年04月21日 10:29
  • 1980
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Java中的编码问题:接收、转码、输出
举报原因:
原因补充:

(最多只允许输入30个字)