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 参考资料

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

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/terrencestark/article/details/73011259

java字符转码:三种方法

原文地址:http://thetopofqingshan.iteye.com/blog/1502731 java字符转码:三种方法 转码成功的前提:解码后无乱码 转码流程:文件(gbk)-->解码-...
  • zhengqiqiqinqin
  • zhengqiqiqinqin
  • 2013-10-11 17:42:04
  • 87339

JAVA中文字符编码问题详解 控制台输出

许多文件的默认编码是ISO-8859-1,而中文操作系统的缺省编码是GB18030,在此工作空间中建立的工程编码是GB18030.我们常用的编码是UTF-8,能够使得插件有更好的国际支持。在编写JSP...
  • qq_35893120
  • qq_35893120
  • 2016-09-09 10:49:16
  • 1222

解决java乱码的问题的两种方式tomcat编码修改

String str = new String(request.getPara
  • bestxianfeng163
  • bestxianfeng163
  • 2018-01-24 09:58:46
  • 34

java 实现16进制与字符互转码

import java.io.ByteArrayOutputStream; public class TesStringToHex {  /**   * @    16进制数字与字符串互相转换 ...
  • zj0910
  • zj0910
  • 2013-08-11 13:45:00
  • 903

深入分析 Java 中的中文编码问题

  • 2014年06月22日 16:29
  • 689KB
  • 下载

java设置字符串编码、转码

String ZB_SB_NO = "fadfadf好的"; new String(ZB_SB_NO.getBytes("ISO8859-1"),"utf-8")
  • heming20122012
  • heming20122012
  • 2017-10-13 19:23:33
  • 113

java输出'联通'记事本的那些乱码

像‘联通’、‘女’之类的在记事本上会显示乱码。为什么会出现以上现象呢? 首先要了解下字符编码知识:详情http://apps.hi.baidu.com/share/detail/17798660; 其...
  • EEXXTTJJSS
  • EEXXTTJJSS
  • 2012-06-22 13:30:15
  • 460

java编码问题的解决办法!!

一、Java中文问题的由来   Java的内核和class文件是基于unicode的,这使Java程序具有良好的跨平台性,但也带来了一些中文乱码问题的麻烦。原因主要有两方面,Java和JSP文件本身...
  • wenjie4892543
  • wenjie4892543
  • 2011-08-18 10:34:50
  • 1070

js中对中文escape转码,java后台通过URL获取中文参数的问题

在做银行支付的时候,需要生成MAC域校验,此时文档中规定对中文参数字段需要用escape转码,在js中通过escape对中文转码后,发现后台接收到的参数为null. 解决办法:转码两次 escape...
  • ljllxk001
  • ljllxk001
  • 2017-06-14 17:20:00
  • 1109

web编码问题小结.doc

  • 2012年01月14日 10:25
  • 35KB
  • 下载
收藏助手
不良信息举报
您举报文章:Java中的编码问题:接收、转码、输出
举报原因:
原因补充:

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