Java开发过程中乱码问题理解
1、Java编译器(即编译成class文件时) 用的是unicode字符集。
2、乱码主要是由于不同的字符集相互转换导致的,理论上各个字符的编码规则是不同的,是不能相互转换的,所以根本解决乱码的方法就是不要转换编码方式,编码方式前 后统一。
3、ASCII、GB2312、GBK、GB18030、Big5、Unicode都是字符集的名称。它们定义了采用1~2个字节的编码规范,为每个字符赋予了一个独一无二的编号。这个编号就是我们所说的“字符编码”。
4、Unicode字符集定义的字符编码并不适合直接通过网络传输表达,因为它们必须转换成像0101这样的二进制字节流传输。所以就出现了不同的转换规范实现方式:UTF-8,TF-16等。这些不同的转换规范转换后的编码值和Unicode是不同的.(unicode是字符集,编码实现是utf-8,utf-16等,unicode到utf-8是有算法的,有统一的规则,但unicode和gbk等其他的编码方式是没有直接联系的不能转换)。
5、不要轻易地使用或滥用String类的getBytes(encoding)方法,更要尽量避免使用getBytes()方法。因为这个方法是平台依赖的,在平台不可预知的情况下完全可能得到不同的结果。如果一定要进行字节编码,则用户要确保encoding的方法就是当初字符串输入时的encoding(即知道以前的编码)。
6、转http://825635381.iteye.com/blog/2087380(java 默认的Unicode和外部资源编码的理解)
new String(input.getBytes("ISO-8859-1"), "GB18030")
上面这段代码代表什么?有人会说: “把input字符串从ISO-8859-1编码方式转换成GB18030编码方式”。如果这种说法正确,那么又如何解释我们刚提到的java字符串都采用unicode编码呢? 这种说法不仅是欠妥的,而且是大错特错的,让我们一一来分析,其实事实是这样的:我们本应该用GB18030的编码来读取数据并解码成字符串,但结果却采用了ISO-8859-1的编码,导致生成一个错误的字符串。要恢复,就要先把字符串恢复成原始字节数组,然后通过正确的编码GB18030再次解码成字符串(即把以GB18030编码的数据转成unicode的字符串)。注意,字符串永远都是unicode编码的.但编码转换并不是负负得正那么简单,这里我们之所以可以正确地转换回来,是因为 ISO8859-1 是单字节编码,所以每个字节被按照原样 转换为 String ,也就是说,虽然这是一个错误的转换,但编码没有改变,所以我们仍然有机会把编码转换回来!
例子如图:
import java.io.UnsupportedEncodingException;
import java.nio.charset.Charset; public class TestChartCode {
public static void main(String args[])
{
System.out.println("系统默认字符集 : "+Charset.defaultCharset());
String str = "abc你好";//string with UTF-8 charset byte[] bytes = str.getBytes(Charset.forName("UTF-8"));//convert to byte array with UTF-8 encode
System.out.println("-------------------将str字符串用UTF-8转为字节数组--------------------------");
for (byte b : bytes)
{
System.out.print(b + " ");
} try
{
System.out.println();
String str1 = new String(bytes, "UTF-8");//to UTF-8 string
String str2 = new String(bytes, "ISO-8859-1");//to ISO-8859-1 string
String str3 = new String(bytes, "GBK");//to GBK string
System.out.println();
System.out.println("-------------------用UTF-8将字节数组转为字符串--------------------------");
System.out.println(str1);//abc你好
System.out.println("-------------------用ISO-8859-1将字节数组转为字符串--------------------------");
System.out.println(str2);//abc??????
System.out.println("-------------------用GBK将字节数组转为字符串--------------------------");
System.out.println(str3);//abc浣犲ソ
System.out.println(); System.out.println("-------------------1.用ISO-8859-1将乱码的字符串转为字节数组--------------------------");
byte[] bytes2 = str2.getBytes(Charset.forName("ISO-8859-1"));
for (byte b : bytes2)
{
System.out.print(b + " ");
}
System.out.println();
System.out.println("-------------------2.用ISO-8859-1将乱码的字符串转为字节数组用UTF-8编码转字符串--------------------------");
String str22 = new String(bytes2, "UTF-8");
System.out.println(str22);//abc你好
System.out.println(); System.out.println("-------------------1.用GBK将乱码的字符串转为字节数组--------------------------");
byte[] bytes3 = str3.getBytes(Charset.forName("GBK"));
for (byte b : bytes3)
{
System.out.print(b + " ");
}
System.out.println();
System.out.println("-------------------2.用GBK将乱码的字符串转为字节数组用UTF-8编码转字符串--------------------------");
String str33 = new String(bytes3, "UTF-8");
System.out.println(str33);//abc你好 } catch (UnsupportedEncodingException e){
e.printStackTrace();
}
} }
控制台输出:
系统默认字符集 : UTF-
-------------------将str字符串用UTF-8转为字节数组--------------------------
- - - - - - -------------------用UTF-8将字节数组转为字符串--------------------------
abc你好
-------------------用ISO--1将字节数组转为字符串--------------------------
abcä½ å¥½
-------------------用GBK将字节数组转为字符串--------------------------
abc浣犲ソ -------------------.用ISO--1将乱码的字符串转为字节数组--------------------------
- - - - - -
-------------------.用ISO--1将乱码的字符串转为字节数组用UTF-8编码转字符串--------------------------
abc你好 -------------------.用GBK将乱码的字符串转为字节数组--------------------------
- - - - - -
-------------------.用GBK将乱码的字符串转为字节数组用UTF-8编码转字符串--------------------------
abc你好
总结: 所以,我们在处理java的编码问题时,要分清楚三个概念:Java采用的编码:unicode,JVM平台默认字符集和外部资源的编码。
7、假如我们需要从磁盘文件、数据库记录、网络传输一些字符,保存到Java的变量中,要经历由bytes-->encode字符-->Unicode字符的转换(例如new String(bytes, encode));而要把Java变量保存到文件、数据库或者通过网络传输,系统要做一个Unicode字符-->encode字符-->bytes的转换(例如String.getBytes([encode]))
例子
package com.bosssoft.platform.appframe.app.controller; import java.io.UnsupportedEncodingException;
import java.nio.charset.Charset; public class Test {
public static void main(String[] args) throws UnsupportedEncodingException { String str = new String("中文".getBytes("gbk"), "gbk");
System.out.println(Charset.defaultCharset()); System.out.println("----------------中文unicode--->gbk");
printBytes("中文".getBytes("gbk"));//unicode--->gbk System.out.println("----------------中文unicode--->utf8");
printBytes("中文".getBytes("utf8"));//unicode--->utf8 str = new String("中文".getBytes("gbk"), "gbk");//unicode---->gbk---->unicode System.out.println("----------------中文unicode---->gbk---->utf8---->unicode---->utf8");
str = new String("中文".getBytes("utf8"), "gbk");//unicode---->gbk---->utf8---->unicode
printBytes(str.getBytes("utf8")); str = new String(str.getBytes("gbk"), "utf8");
System.out.println(str); //bytes数组,charset是字节数组安装什么方式编码生成字符串
//new String(bytes, charset)
System.out.println(new String(str.getBytes("utf8"), "utf8"));
byte[] jvmBytes = str.getBytes("unicode");
System.out.println("jvm Encoding: " + bytesToHexString(jvmBytes)); byte[] defaultBytes = str.getBytes();
System.out.println("page Encoding:" + bytesToHexString(defaultBytes)); byte[] utf8Bytes = str.getBytes("utf8");
System.out.println("uft8: " + bytesToHexString(utf8Bytes)); byte[] gb2312Bytes = str.getBytes("gb2312");
System.out.println("gb2312: " + bytesToHexString(gb2312Bytes)); byte[] gbkBytes = str.getBytes("gbk");
System.out.println("gbk: " + bytesToHexString(gbkBytes)); byte[] gb18030Bytes = str.getBytes("gb18030");
System.out.println("gb18030Bytes: " + bytesToHexString(gb18030Bytes)); byte[] iso8859_1Bytes = str.getBytes("iso8859-1");
System.out.println("iso8859-1: " + bytesToHexString(iso8859_1Bytes)); for(int i=; i<iso8859_1Bytes.length; i++) {
System.out.println(iso8859_1Bytes[i]);
}
} /**
* byte数组转换成16进制字符串
* @param src
* @return
*/
public static String bytesToHexString(byte[] src){
StringBuilder stringBuilder = new StringBuilder();
if (src == null || src.length <= ) {
return null;
}
for (int i = ; i < src.length; i++) {
int v = src[i] & 0xFF;
String hv = Integer.toHexString(v);
if (hv.length() < ) {
stringBuilder.append();
}
stringBuilder.append(hv);
}
return stringBuilder.toString();
} public static void printBytes(byte[] src) {
for (byte b : src) {
System.out.print(b + " ");
}
System.out.println();
}
}
8、前面提到从ASCII、GB2312、GBK到GB18030的编码方法是向下兼容的。而Unicode只与ASCII兼容(更准确地说,是与ISO-8859-1兼容),与GB码不兼容。例如“汉”字的Unicode编码是6C49,而GB码是BABA。(简单来说有两大阵营ANSI和unicode不能相互转换除了ISO-8859-1,因为他有单字节的特殊性)
9、String name = "我来了";
String str = new String(name.getBytes("x"),"xxx");
不管jvm这里默认的编码是GBK还是UTF-8还是其他编码,name.getBytes("x")java都会自动帮你转成Unicode编码,然后再以x的编码方式转成xxx的编码字符集。
例如:如何GbK转成UTF-8,真正的核心问题是GBK怎么转成unicode(无法直接转只能找GBK和unicode对照表),转成unicode以后转utf-8就好转了(因为有规律)。java特殊因为java 字符串都是默认unicode的(生产的class文件都是 unicode字符集),所以无论你name.getBytes("xx")是什么编码得到的unicode值都是unicode字符集的正确值。(既然java字符默认都转成了unicode那么为什么GBK转UTF-8为什么还是乱码?java都做到默认转unicode编码了可以实现不乱码了,不知内部为什么?),所有有人在java语言中也有实现GBK转UTF-8,其实就是直接unicode转utf-8。
Java开发过程中乱码问题理解的更多相关文章
- android(java) 开发过程中经验及总结记录
android(java) 开发过程中经验及总结记录
- 【Java基础】Java开发过程中的常用工具类库
目录 Java开发过程中的常用工具类库 1. Apache Commons类库 2. Guava类库 3. Spring中的常用工具类 4. 其他工具 参考 Java开发过程中的常用工具类库 1. A ...
- java开发过程中从前台传到后台中文乱码《filter》
在企业开发中,最常见的是javaweb项目,有web项目就免不了和后台打交道,比如我从jsp页面发送新增请求到后台,后台可能是servlet.struts2.springmvc等,这时就存在一个问题, ...
- Java Web中乱码问题
response.setContentType("text/html;charset=UTF-8"); 用于定义网络文件的类型和网页的编码,决定浏览器将以什么形式.什么编码读取这个 ...
- JAVA EE中session的理解
转自[互动百科]http://www.baike.com/wiki/Session Session Session:在计算机中,尤其是在网络应用中,称为“会话”.Session直接翻译成中文比较困 ...
- Java/Java Web中乱码解决汇总
在开发Java/Java Web Application过程中,往往会出现乱码问题,而且有的时候真会弄得人很烦,浪费太多的时间. 记得之前看过一篇帖子,详细解释了Encoding/Decoding过程 ...
- java web中乱码的种类和一些解决方式
在java web课堂测试中遇到了一些乱码问题 ,从百度上找到了许多种解决方法和乱码的种类,在这里总结一下. 一.文件出现乱码 [右击文件]->[Properties]->[Resourc ...
- Java开发过程中开发工具Eclipse中导入jar包的过程
欢迎欣赏我的第二篇随笔.我们在创建好一个动态网站项目之后,如果没有部署maven的情况下,你可以按照以下的方法,直接把要用的jar包导入你的工程中,而不用再部署maven. 例如在使用JDBC编程时需 ...
- java开发过程中,报错Dangling meta character '*' near index 0,解决办法
1.split方法转化字符串为数组: String[] strPicArr = map.get("hw_pic").toString().split("*"); ...
随机推荐
- Shell脚本监控专线Network并SendEmail报警
Much effort, much prosperity. 配置服务器监控专线网络 项目介绍: 配置一台服务器监控专线网络的情况,(由于公司业务的原因需要用到专线进行与客户对接)实时监控专线的状态,如 ...
- 深入解析Linux内核及其相关架构的依赖关系
Linux kernel 成功的两个原因: 灵活的架构设计使得大量的志愿开发者能够很容易加入到开发过程中:每个子系统(尤其是那些需要改进的)都具备良好的可扩展性.正是这两个原因使得Linux kern ...
- idea技巧
写在前面 以前一直用的elipce,如今入坑IntelliJ IDEA,没想到啊.深深的爱上了它,强大到无所不能: "工欲善其事必先利其器",IntelliJ IDEA作为一个非常 ...
- idea中git合并切换分支等操作
https://blog.csdn.net/autfish/article/details/52513465
- hibernate的一对多配置
首先是“一”的 Customer.java package com.xiaostudy.domain; import java.util.HashSet; import java.util.Set; ...
- Java socket - 使用代理服务器
为什么使用代理服务器不需要多说了. 使用Proxy Java提供了Proxy类实现使用代理进行通信. Proxy类的构造器Proxy(Proxy.Type type, SocketAddress sa ...
- Dynamo概述
Dynamo 是Amazon提供的一款高可用的分布式Key-Value存储系统,其满足可伸缩性.可用性.可靠性. CAP原理满足:通过一致性哈希满足P,用复制满足A,用对象版本与向量时钟满足C.用牺牲 ...
- HTTP和HTTPS的区别和联系
超文本传输协议HTTP协议被用于在Web浏览器和网站服务器之间传递信息,HTTP协议以明文方式发送内容,不提供任何方式的数据加密,如果攻击者截取了Web浏览器和网站服务器之间的传输报文,就可以直接读懂 ...
- 分享知识-快乐自己:能使 Oracle 索引失效的六大限制条件
Oracle 索引的目标是避免全表扫描,提高查询效率,但有些时候却适得其反. 例如一张表中有上百万条数据,对某个字段加了索引,但是查询时性能并没有什么提高,这可能是 oracle 索引失效造成的.or ...
- jenkins 环境搭建与入门示例
环境说明: 1.win7 2.tomcat 9.0.0.M17 3.jenkins 2.32.2.war jenkins 环境搭建 1.下载jenkins部署包 https://jenkins.io/ ...