源自:http://blog.csdn.net/WebDynpro/archive/2006/10/09/1326614.aspx

在java中的字符均采用字符集UCS-2(编码为UTF-16,UCS-2可以看作所有字符集的超集

.其他字符集都可以映射到UCS-2).而外部编码却很多种.字符有两个流向:从系统流向jvm中

运行的程序,由jvm中运行的程序流向系统.在这过程中都有可能出现乱码.

因而这两个流向均存在编码和解码的问题.

先明确几个概念,编码和解码(encode/decode),在java中解码是指把某种编码的字符

转为UCS-2字符集中对应的字符,编码是指把UCS-2字符集中的字符转为某种编码的字符.乱

码,乱码分两种,一种是由于系统没有使用正确的编码无法正确显示,一种是由于字符处理错

误导致产生不可识别的内容.虽然看上去的现象相同,但两者是不同的,前者可以通过使用合

适的编码显示,本身是没有错误的,后者则不可.我在这里所说的乱码主要指第二种.

java默认的输入输出编码为操作系统的默认编码.因此我们处理本地编码的文件很少遇

到乱码的问题.

我们可以在输入和输出时选择编码方式.以正确处理其他编码的文件.

从外部的字符以原来的编码读入可以正确地用UCS-2字符集中的字符表示.因此可以在

程序中正常处理.比如有一个日文Shift-jis编码的文件.用如下方式即可

BufferedReader in = new BufferedReader(new InputStreamReader(new FileInput

Stream(inFile), "SJIS"));

如果以其他编码方式读入,显然得到的数据是乱码的,而且这个过程是不可逆的,那上面

这个例子改一下:

BufferedReader in = new BufferedReader(new InputStreamReader(new FileInput

Stream(inFile), "GB2312"));//乱码出现的源头在这一句

String line = in.readLine();

System.out.println(new String(line.getBytes("GB2312"), "SJIS"));//将输出乱

码,Shift-JIS编码的文件以GB2312方式读入时无法正确映射到UCS-2上,因为Shift-JIS的很

多字符的编码在GB2312中是不存在的,用getBytes("GB2312")读出的字节流和输入时的字节

流已经不同,无法再正确地转为SJIS.

但是如果把GB2312编码方式改为8859_1(ISO-8859-1,8位编码,兼容我们常用的ASCII字

符集的编码),却是可以的.这个特殊情况的出现是有原因的.因为ISO-8859-1以字节为单位

编码,而每个字节其编码中都有对应字符,从ISO-8859-1映射到UCS-2上,再从UCS-2编码为I

SO-8859-1,这两个过程是互逆的对应的,这个特性有个特殊的应用,后文中将提到.我们在网

上常见到用getBytes("ISO-8859-1")这种方式来获取乱码前的字节流,但这应该算是一个特

例,只能用于以ISO-8859-1编码方式的错误读入的字符流.

同样的,从UCS-2字符集到其他编码如果采用了错误的编码方式也会造成乱码,且过程不

可逆,甚至包括ISO-8859-1编码.即对于

String myStr = "字符串"'

String convertedStr = new String(myStr.getBytes("ISO-8859-1"), "ISO-8859-1

");

myStr.equals(convertedStr)将为false.

故而我们可以知道,对于java的字符乱码,产生的源头有三个:

一.从源字符流到UCS-2的转换过程;

这是因为原字符流以错误的编码转换为UCS-2,而原编码和转换用的编码不兼容,这一转换

过程完成后不可逆,即以错误编码得到的字符无法还原成正确的编码.例如前面把Shift-JI

S编码的文件以GB2312格式读入.

看看下面的例子:

假设有GB2312的字符保存在文件inFile中

1.BufferedReader in = new BufferedReader(new InputStreamReader(new FileInp

utStream(inFile), "GB2312"));

String line = in.readLine();//得到正确的字符

2.BufferedReader in = new BufferedReader(new InputStreamReader(new FileInp

utStream(inFile), "GBK"));

String line = in.readLine();//得到正确的字符,GBK完全兼容GB2312编码,GB231

2编码的字符完全可以以GBK读入,反之则可能出现部分乱码,因为GBK中存在GB2132没有定义

的字符

3.BufferedReader in = new BufferedReader(new InputStreamReader(new FileInp

utStream(inFile), "SJIS"));

String line = in.readLine();//得到乱码字符,GB2312与Shift-JIS不兼容

二.从UCS-2到字符流的转换过程;

这是由于UCS-2表示的字符在要转向的编码中不存在对应的字符,导致转换出错,得到乱码

.如

String chars = "我们";//"我们"采用的是Java内部的字符集UCS-2

String chars_converted = new String( chars.getBytes("ISO-8859-1"), "UTF-16");

//getBytes()将UCS-2字符编码为英文字符集ISO-8859-1,但ISO-8859-1并不包含"我们"这

两个字符,所以错误地编码了,此过程同样不可逆,我们无法用java提供的api将其还原成原

来的字符

看看下面的例子:

String chars = "我们";

String chars_enGB2312 = new String(chars.getBytes("GB2312"), "GB2312");

System.out.println( chars.equals(chars_enGB2312));//true!

String chars_enUTF8 = new String(chars.getBytes("UTF-8"), "UTF-8");

System.out.println( chars.equals(chars_enUTF8));//true!

String chars_enSJIS = new String(chars.getBytes("SJIS"), "SJIS");

System.out.println( char.equals(chars_enSJIS));//false!日文Shift-JIS中没有"们

"字,如果去掉"们"字将为true

以上例子只为说明UCS-2到其他编码的转换,实际上并不推荐上面这种做法,因为UCS-2是差

不多是所有字符集的超集,从超集到子集的转换,除非能保证所用字符在子集上,否则很容易

出现乱码.

实际问题中第一种情况最为常见,第二种是多数是字符从外部读入保存在String中进一步

处理是发生,实际上,我认为getBytes()编码后得到的字节流只应该用其超集再编码.

三.从java程序中向系统输出字符流

向系统中写出字节流的时候面临的问题和读入时是一样的,如果我们处理的不是使用系统

默认编码的字符,则输出时应该注意以合适的编码输出,否则会产生不可识别的乱码.

对于iso-8859-1编码,如前面提到的,以ISO-8859-1编码读入并表示为UCS-2字符,然后再以

ISO-8859-1编码将得到原始编码的字符流.即iso-8859-1到UCS-2,再由UCS-2到iso-8859-1

是可逆的.可以用来在不支持其他字符集的机器上处理和存储其他编码的字符(当然不能显

示),而且也可输出原编码的字节流.

假设inFile为GB2312编码的文件,

BufferedReader in = new BufferedReader(new InputStreamReader(new FileInputStr

eam(inFile), "ISO-8859-1"));

String line = in.readLine();

String out = new String(line.getBytes("ISO-8859-1"), "GB2312");//得到正确的GB

2312编码字符

Note:1.utf-8采用2/3混编的方式。目前容纳的汉字范围小于gbk编码。

2.按照GBK18030、GBK、GB2312的顺序,3种编码是向下兼容.

3.utf-8只兼容iso-8859-1,对于其他编码方式并不兼容.很多文章提到utf编码兼容很

多其他编码的提法其实只是表明,其他编码中的字符在utf-8中有对应的字符,但他们的位置

并不相同.而且存在其他编码有的字utf没有的情况.如1中提到的gbk.

呼~总算写完了.网上很多写java乱码问题的很多都写得不清不楚,错漏百出,自己研究

了一下.不过对于服务器端编程时容器代来的乱码的问题似乎比较难深入系统分析,各个服

务器之间也似有不同.

分享到:

2009-11-03 14:10

浏览 3262

评论

1 楼

darkjune

2012-06-05

写的很好, 支持一下

java sjis_java乱码分析相关推荐

  1. Java Web乱码分析及解决方式(一)——GET请求乱码

    引言:     在进行Web開始时.乱码是我们最常常遇到也是最主要的问题.有经验的程序员非常easy能解决,刚開始学习的人则easy被泥潭困住. 并且非常多时候.我们即使攻克了乱码问题也是不明就里.往 ...

  2. Java Web乱码分析及解决方案

    1.  什么是URL编码. URL编码是一种浏览器用来打包表单输入的格式,浏览器从表单中获取所有的name和其对应的value,将他们以name/value编码方式作为URL的一部分或者分离的发送到服 ...

  3. 分析java中文乱码的原因

    在java开发中都能遇到java中文乱码的情况,怎样才能够恰当地选择汉字编码方式并正确地处理汉字的编码呢?希望通过下面的总结的java中文乱码解决方法对遇到过此类问题的朋友有所帮助. 首先,要想解决j ...

  4. java菱形乱码 编码_JAVA:编码与乱码问题

    一.为什么要编码? 由于人类的语言太多,因而表示这些语言的符号太多,无法用计算机的一个基本的存储单元----byte来表示,因而必须要经过拆分或一些翻译工作,才能让计算机能理解. byte一个字节即8 ...

  5. J2EE (六) 详解 java 中文乱码

    简介 在Java项目的开发过程中,经常会出现中文乱码的情况,这也是一直是困扰大家的一个问题,很多的程序员都会经常遇到这个问题. 有时捣鼓调试半天也摸不着头绪,不知道究竟哪里出了问题,那是你还不清楚出现 ...

  6. java ssh乱码_SSH框架下中文字符乱码问题的研究

    1 Java中文乱码问题的产生原因 在Java Web的应用中,中文字符乱码问题是个由来已久和让人头疼的问题,尤其是刚刚接触Java Web编程的人员,往往在解决中文字符乱码问题上花费了大量的时间和精 ...

  7. java word 乱码_java另存word时出现乱码怎么办

    java另存word时出现乱码怎么办 发布时间:2020-04-07 11:05:31 来源:亿速云 阅读:92 作者:小新 这篇文章主要为大家详细介绍了java另存word时出现乱码怎么办,文中示例 ...

  8. java反射最佳实践,java反射性能测试分析

    java反射性能测试分析 java有别于其他编程语言而让我着迷的特性有很多,其中最喜欢的是接口设计,他让我们设计的东西具有美感.同样反射也是我比较喜欢的一个特性,他让程序自动运行,动态加载成为了可能, ...

  9. java中文乱码解决之道(二)—–字符编码详解:基础知识 + ASCII + GB**

    原文出处:http://cmsblogs.com/?p=1412 在上篇博文(java中文乱码解决之道(一)-–认识字符集)中,LZ简单介绍了主流的字符编码,对各种编码都是点到为止,以下LZ将详细阐述 ...

  10. cmd运行Java中文乱码,无法加载主类Error: Could not find or load main class

    网上说了好多方法,只说我用了的 cmd运行Java中文乱码 设置环境变量--系统环境变量 添加条目:JAVA_TOOL_OPTIONS 值:-Dfile.encoding=UTF-8 -Duser.l ...

最新文章

  1. 关于Input内容改变的触发事件
  2. Spring: 依赖注入的实现
  3. linux安卓双系统板子,安卓迷你 PC 主机只要 109 美元,支持 Android 和 Linux 双系统...
  4. (九十三)蓝牙的基本使用
  5. bash ./php-memcache.sh,PHP+shell脚本操作Memcached和Apache Status的实例分享
  6. Java聊天室2.0版本
  7. 详解OpenCV中的cvCreateMat()函数
  8. 羽枭android,【答疑】Unreal Engine 4 是怎样发布android的? - 视频教程线上学
  9. 怎么把 html做成雪花特效,CSS3 HTML5下雪特效 雪花飘飘
  10. 本地升级MySQL数据库版本为8.0.23,使用SQLyog(小海豚)无法进行连接
  11. 运维学python perl go_公开课|一个小运维的《Golang 入门心路历程》
  12. c语言单片机循环程序,单片机c语言教程:C51循环语句
  13. jdk api 1.8中文手册
  14. pc电脑版java模拟器下载安装_PC电脑版java模拟器
  15. java实现fp-growth算法
  16. 小水智能-智能楼宇智慧建筑3D可视化系统,实现对实时数据的整合处理
  17. OpenGauss数据库的安装与运行
  18. uboot利用uEnv.txt文件实现灵活功能(加载PL侧bit,修改uenvcmd,配置bootargs,配置bootm,配置bootz)
  19. Illumina测序什么时候会测序到接头序列?
  20. 基片集成波导原理_双膜基片集成波导(SIW)带通滤波器的设计与HFSS仿真

热门文章

  1. [转]架构蓝图--软件架构 4+1 视图模型
  2. Protel99se常用快捷键
  3. cadence入门学习
  4. 百度文库免费下载,亲测,原格式文档
  5. Python入门经典. 以解决计算问题为导向的Python编程实践
  6. 软件项目需求分析报告模板
  7. Git 图解、常用命令和廖雪峰教程笔记总结
  8. 抓包工具——【Mac】Charles的下载和安装
  9. t580 thinkpad_ThinkPad T580性能如何?联想ThinkPad T580商务本详细评测
  10. linux系统添加任务栏蓝牙图标,深度系统中(deepin os)如何使用蓝牙适配器