`

java乱码分析

阅读更多

源自: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乱码问题的很多都写得不清不楚,错漏百出,自己研究
了一下.不过对于服务器端编程时容器代来的乱码的问题似乎比较难深入系统分析,各个服
务器之间也似有不同.

分享到:
评论
1 楼 darkjune 2012-06-05  
写的很好, 支持一下

相关推荐

    JAVA中文乱码深度分析

    Java使用Unicode作为内部编码,这允许其跨平台兼容性,但同时也引出了中文乱码的问题。当Java程序在不同的操作系统或浏览器上运行时,如果没有正确处理编码转换,就可能导致乱码。 1. 中文问题的来源: - Unicode...

    java中文乱码分析

    ### Java中文乱码分析 #### 一、概述 在Java Web开发中,中文乱码问题是一个常见的技术难题,尤其在处理HTTP请求时尤为突出。本文将深入探讨HTTP请求中的中文乱码现象,并提供相应的解决方案。 #### 二、HTTP请求...

    java乱码自己解决的办法

    本文将深入探讨Java乱码的根源,并提供一系列实用的解决方案,帮助开发者有效应对这一挑战。 ### Java乱码根源 Java乱码主要由编码不一致引起,具体来说,当数据在不同环境(如输入、存储、读取)中采用不同的字符...

    java中文乱码解决问题

    下面我们对容易产生乱码问题的场景进行分析,并提出解决方案。 1. 以 POST 方法提交的表单数据中有中文字符 在 Servlet/JSP 程序中,通过请求对象的 getParameter() 方法得到的字符串是以 ISO-8859-1 转换而来,这...

    Java乱码问题解决

    ### Java乱码问题详解与解决方案 #### 一、问题背景 在Java开发过程中,尤其是在处理中文字符时,经常遇到字符编码不一致导致的乱码问题。由于Java默认使用Unicode编码,而在中国大陆地区,常见的字符集为GB2312...

    java获取乱码问题

    ### Java获取乱码问题解析与解决方案 在Java应用开发过程中,字符编码问题一直是困扰开发者的一大难题,尤其是在处理HTTP请求中的中文或特殊字符时,经常会出现乱码现象。本文将详细介绍如何通过修改`server.xml`...

    java中文乱码问题

    今天,我们将从编码角度分析 Java 编译后在控制台和 Web 等终端显示乱码问题。 一、 Java 处理字符的原理 Java 使用 UNICODE 来存储字符数据,处理字符时通常有三个步骤:按指定的字符编码形式,从源输入流中读取...

    java中文乱码问题解决

    本文将深入分析Java中文乱码问题的根本原因,介绍各种编码格式的区别和应用场景,并提供解决乱码问题的方法和经验。 在Java中,常见的编码格式有: * ASCII码:总共有128个,用一个字节的低7位表示,0~31是控制...

    java插入mysql中文乱码解决

    #### 二、乱码原因分析 中文乱码主要由以下几个方面的原因引起: 1. **字符集不一致**:如果Java程序、JDBC驱动、MySQL服务器以及数据库表的字符集设置不一致,就会导致中文乱码。例如,如果Java程序使用的是GBK...

    JAVA反编译文件解决中文乱码

    在Java开发过程中,有时我们需要查看或分析已编译的.class文件中的源代码,这就涉及到Java的反编译技术。反编译是将字节码还原为接近原生的源代码的过程,常用工具有JD-GUI,它是一款直观的Java反编译器。然而,当...

    Java中文乱码解决之道

    阅读许多关于中文乱码的解决办法的博文后,发现对于该问题我们都(更加包括我自己)没有一个清晰明了的认识,于是LZ想通过这系列博文(估计只有几篇)来彻底分析、解决java中文乱码问题,如有错误之处望各位同仁指出...

    java乱码的解决方案

    ### Java乱码问题及其解决方案 在Java开发过程中,字符编码问题常常导致中文显示为乱码。乱码问题可能出现在各种场景下,例如JSP页面、Servlet处理请求等。本篇文章将详细探讨Java乱码问题产生的原因及解决方案。 ...

    java中文乱码字符集解决大全.pdf

    本文将详细分析这个问题的来源、Java编码转换的过程以及解决策略。 1. 中文问题的来源 早期的计算机系统主要支持单字节的字符编码,如ASCII,无法满足多语言环境的需求。Unicode编码应运而生,它使用双字节表示...

    Java中压缩与解压--中文文件名乱码解决办法

    ### Java中压缩与解压——中文文件名乱码解决办法 #### 一、问题背景及原理分析 在Java中处理文件的压缩与解压时,经常会遇到中文文件名出现乱码的问题。这个问题主要源于Java中默认使用的编码方式与实际文件名...

    解决java所有中文乱码集合

    二、乱码问题分析 1. HTTP头设置:HTTP头中的"Content-Type"字段应指定正确的字符集,例如"Content-Type: text/html; charset=UTF-8",确保数据传输时的编码。 2. JSP页面设置:在JSP页面顶部添加;charset=UTF-8"%...

    java编码格式(对常见的java中文乱码作出分析及提出解决方案)

    Java编程中的中文乱码问题是一个常见但棘手的挑战,主要源于编码格式的不匹配和转换过程中的错误。本文深入探讨了这个问题,并提供了解决方案。 首先,我们要理解中文字符编码的历史背景。早期的计算机系统主要支持...

    Java中文乱码问题研究.pdf

    针对客户端和服务器端传输数据,客户端显示中文字符编码,及应用程序与数据库之间的数据交互等问题,分析了Java乱码产生的原因,并针对每种情况,结合实际的项目开发经验,给出了设置页面编码方式、修改Web服务器...

    中文乱码问题分析 自己总结的

    中文乱码问题分析 中文乱码问题是 Java 和 JSP 开发中的一种常见问题,主要是由于 Java 和 JSP 源文件的保存方式是基于字节流的,而编译成 class 文件过程中,使用的编码方式与源文件的编码不一致所致。在 Java ...

Global site tag (gtag.js) - Google Analytics