`

java字符编码原理解析

    博客分类:
  • j2se
 
阅读更多

什么是字符,什么是字节?

可以理解为计算机没有字符的概念,只有字节。字符是存在于人类语言层的概念,其作用是为了人与人之间的交流,因为字节对于人类是不可读的,但是计算机存储所有的数据都是按照字节存储。
因此要将人类意识中的字符存储到计算机中,则必须将字符转换为字节数据,那么怎么转化呢,则必须要一种映射规则,这里的映射规则就是通常意义中的字符编码,比如说该文件是GBK编码,可以说为:这个文档中的字符数据是按照GBK这种字符字节映射规则将字符转换为字节存储的。

所以所有要将人类意识中的字符存储在计算机或者需要通过计算机传递时,都涉及到字符和字节之间的通过某种映射规则的转换。

将字符按照映射规则转化为字节称为编码,反之称为解码。

弄明白了字符和字节,以及为什么要编码解码的意义,在看在java中哪些地方需要编码:

1:java的源代码文件.我们在使用编辑器编辑数据后,需要将编辑器中的”字符们“存储起来时,需要选择一种映射规则存储在计算机中。当编译java源代码时,javac读取源代码文件,得到源代码文件的字节数据后,需要将其转换为字符,那么就必须按照刚刚存储源代码时选择的映射规则同样的
映射规则才能将这些字节正确还原为人类意识中的字符,然后再将这些字符使用utf-16映射规则映射为字节存储在.class中。所以在编译java源代码时,必须指定源代码的字符字节映射规则(编码),如果指定错了,那么映射回来的字符就会出错。
注:javac默认采用本地编译平台的编码读取源代码文件。所以如果开发团队中有些人是日文系统,有些是中文系统,但是又没有统一源代码编码,上传到cvs后,后来又在utf-8上编译,呵呵,全乱了。

2:控制台的编码:当我们在java代码中使用System.out.println();输出字符时,向操作系统传递数据,让操作系统再显示出来。这中间也存在编码。记住:所有涉及字符的地方都涉及编码。因为底层都是通过字节传递的,要通过字节传递就必须选择一种字符字节映射规则。
  试想在java端我们采用一种映射方式将字符映射为字节,将这些字节发送给操作系统,操作系统得到字节数据,然后再使用某种映射方式将字节映射回字符。如果采用的映射方式不对也就会产生显示出不可预测的数据,不是用户希望的结果,这就是乱码
  而java实现的时候是采用的本地操作系统默认的映射方式将字符映射为字节,操作系统也是采用默认的将字节映射回字符,因此这个过程中是不会出现任何错误的。那么我们在控制台看见的乱码是因为在java内存中还是字符时这个时候这个字符就已经不是你所希望看见的了。
  如上面说的源代码编码,如果编译的时候指定编码错误,那么将源代码字节映射为字符就已经出错,然后将错误的字符采用utf-16映射为了字节,运行的时候再将这些字节映射为字符,这个时候的字符就已经是错的了(这个字符是本来是utf-16映射规则映射成的字节但是后来又按照gbk映射
  规则映射成的字符。和控制台出现乱码容易混淆的情况是远程控制的时候如使用ssh,因为这个时候又多了一层ssh服务端向ssh客户端发送将字符按照某种映射规则映射成的字节数据和ssh客户端选取一种映射规则将字节映射为字符的情况。
 
3:JSP文件的编码。在JSP中使用pageEncoding指定jsp源文件的编码。原理和上面第一条中的java源代码一样。但是为什么jsp需要而.java文件不需要呢。因为jsp是在服务器上编译的。你在本地机上写jsp文件,存储的为默认编码GBK,到服务器上以后万一服务器为utf-8编码,如果采用和.java一样的策略不是就会出错了吗。


4:web服务端向浏览器发送数据:因为要通过网络传递字符数据,所以需要将字符按照某种方式映射为字节,在浏览器端,浏览器接收到字节数据再选取某种映射方式反映射为字符供用户观看。同样,如果选取的影射方式不匹配就会出错。所以可以让服务器将编码方式告诉客户端。在HTTP的报
 文头中可以包含这些信息(如Content-Type: text/html;charset=GBK),这可以通过response.setContentType实现(在jsp中使用<%@ page contentType=""%>指令将转化为response.setContentType代码)。如果在jsp中指定了pageEncoding但是没有指定contentType,生成的servlet代码中默认使用pageEncoding的编码设置contentType.如果没有设定contentType服务器(tomcat)默认设定为iso-8859-1。

5:浏览器向服务器发送的数据(和浏览器以及浏览器的配置相关):同样也要通过网络传输。所以需要知道客户端采用的是什么映射规则将用户输入的字符映射为字节传递给服务端.客户端一般采用的是该页面的编码发送数据(这个我没有认真测试过),但是web服务器(tomcat)确是默认采用iso-8859-1映射规则,所以双方的映射规则不一致。解决方案就是
 request.setCharacterEncoding设置服务器针对浏览器发送来的字节数据的映射规则(不同的服务器该方法实现策略可能不一样,在项目中遇到过weblogic和tomcat不一样,weblogic该方法会将HTTP头和内容块数据都采用该方法的参数设置映射规则,但是在tomcat中该映射规则只用于内容块,而报文头的映射规则在server.xml的connector的URIEncoding配置).
 不同的浏览器可能也存在不同。我在IE6中测试服务器发送utf-8的编码,通过抓包发现服务器发送下来的数据的确是utf-8的,但是如果通过url传递如<a href="1.jsp?a=趁"/>结果发现IE传递的是e8,b6(少了一个字节),而"趁"的utf-8编码是e8,b6,81。但是如果通过form提交,不管是用get/post方法,传递的都是"%e8,%b6,%81"
 这种以“%”开始的编码是将二进制使用十六进制表示。但是在opera中,上面的三种方法都传递的是"%e8,%b6,%81".那么如果服务器发送的是gbk编码呢?呵呵自己测试试

6:javascript编码:javascript和浏览器也有关系,IE中,如使用XMLHTTPRequest的open方法调用open("GET", "2.jsp?a=人");虽然当前页面是utf-8编码,但是javascript传递的是c8cb,这是"人"的gbk编码。而在opera中传递的是%E4%BA%BA,是正确的.如果服务器发送的字节是utf-16编码,IE中仍然传递的是"人"的gbk编码,opera也仍然传递的是utf-8的编码。
  不知道浏览器是不是可以在哪儿配置

7:数据库编码:数据库不好测试,因为还涉及到数据库客户端编码的问题。如果将正确的字符按照数据库指定的编码存储在数据库文件中,当查询数据时,数据库服务器将正确的字符发送给了客户端,但是客户端字符字节映射规则如果设置错误,可能会导致用户错误地认为数据库中存储的是错误的字符。最好的办法是抓包分析,但是数据库协议非常复杂,又无法抓包,
  但是如果在某个过程中发生了出错,原理和上面描述的一样,一定是浏览器<->web服务器,web服务器<->数据库,数据库<->数据库客户端,ssh客户端<->ssh服务端等等之间某个地方出现了问题。   

要解决双方选择的字符字节映射规则不一致而导致的乱码问题:
1:是告诉对方自己采用的什么映射规则将字符转换为字节的
2:用协议约定,约定双方都用某个规则映射
3:类似于XML在第一行标志下面的数据是采用什么映射规则映射的
4:在文件头存储特殊字节标志映射规则,如windows处理utf-16(会导致如果"联通"两个字出现在文件开始的话出现问题,大家可以到网上搜索一下这个情况,分析分析,呵呵)

分享到:
评论

相关推荐

    java字符串编码转换

    为了正确地解析这些数据,可以使用 `request.setCharacterEncoding()` 方法来设置请求的字符编码: ```java request.setCharacterEncoding("UTF-8"); ``` 这一步非常重要,因为它确保了从请求中读取的所有数据都...

    Java字符编码原理(动力节点Java学院整理)

    Java字符编码原理是Java开发中不可或缺的基础知识,尤其是在处理涉及多语言环境的系统时,对字符编码的理解至关重要。本文将深入探讨Java中的字符编码过程,帮助开发者解决常见的乱码问题。 首先,Java源代码文件...

    JAVA 转换字符编码工具

    在实际应用中,字符编码问题可能导致乱码、数据丢失或者无法正确解析的问题。例如,从GBK编码的文本读取数据并试图用UTF-8解码,就会导致无法识别的字符。因此,这样的工具通常会包含以下功能: 1. **编码识别**:...

    Java中的字符集编码入门(五)Java代码中的字符编码转换Part1.doc

    本文档深入探讨了Java编程语言中字符集编码的基础知识,并着重讲解了字符编码转换的基本原理及其在Java代码中的应用。文档强调了在Java虚拟机(JVM)内部字符统一采用UTF-16编码格式的重要性,并详细解释了如何实现...

    Java IO流常用字节字符流原理解析

    "Java IO流常用字节字符流原理解析" Java IO流中有两种基本的流类型:字节流和字符流。在Java IO流中,字节流是指以byte为单位进行操作的流,而字符流是指以char为单位进行操作的流。今天,我们将主要介绍Java IO流...

    java对mht文件解析

    本文详细介绍了使用Java解析MHT文件的基本原理和技术实现,包括如何提取HTML内容、解码Quoted-Printable编码、构建DOM树以及提取所需数据。这对于需要处理MHT文件的应用开发具有很高的参考价值。

    深入UTF8字符编码.pdf

    在JAVA开发环境中,源代码文件、编译过程以及运行时环境的字符编码一致性是保证代码正确执行的关键。JAVA编译器默认使用系统默认编码进行源代码文件的读取和编译,但在复杂环境中,手动设置编码至如UTF-8这样更为...

    字符转换工具类

    在Java编程中,字符编码是一个关键概念,因为不同的编码标准(如ASCII、GBK、UTF-8等)可能对同一字符有不同的表示方式。例如,ASCII主要支持英文字符,而GBK和UTF-8则支持更多的汉字和其他语言字符。在处理字符串时...

    java中BCD编码

    - `fromHexString(String hex)`:将十六进制字符串解析为BCD编码的字节数组。 在实际开发中,BCD编码常用于金融系统,如银行、支付平台等,处理金额时需要保证精度,避免浮点数计算误差。同时,BCD编码也有利于减少...

    字符集编码

    不同语言、不同系统间的字符编码差异可能导致数据在传输过程中出现乱码等问题。因此,理解字符集编码的基本原理及如何在实际开发中正确配置和使用它们至关重要。 #### 二、编码基本知识 ##### 2.1 ISO 8859-1 - *...

    Java 自动识别编码

    "Java 自动识别编码"这个主题涉及到的是Java编程语言如何自动检测文本文件或数据流的字符编码方式,以便正确地读取和解析其中的内容。下面将详细探讨这个知识点。 首先,Java中的`Charset`类是处理字符编码的基础,...

    cxf3.2.0编码GBK的不可映射字符问题

    总的来说,解决CXF3.2.0的GBK编码问题需要理解字符编码的工作原理,并对CXF的配置和处理流程有深入的了解。通过上述方法,可以有效地避免和处理这种不可映射字符的错误,保证服务的正常运行和数据的准确传输。在实际...

    java自动识别网站 文件的编码

    总结来说,自动识别网站文件的编码在Java开发中是一项重要技能,涉及到字符编码的基本原理、Java的IO流操作以及第三方库的使用。通过对给定的代码和示例进行学习,开发者可以更好地处理各种编码问题,提高数据处理的...

    java 字符串线输出大写后输出小写

    ### Java字符串操作:按字符大小写分类输出 在Java编程语言中,字符串处理是一项非常重要的技能,尤其是在数据清洗、文本分析等应用场景下。本篇文章将详细介绍如何实现一个简单的程序,该程序可以接收一个字符串...

    常用的java汉字unicode编码

    Unicode是一种国际化的字符编码标准,旨在为世界上所有的字符提供唯一的数字编码,这包括了汉语中的每一个汉字。在给定的文件中,虽然部分内容难以直接解析为明确的IT知识,但通过其标题“常用的java汉字unicode编码...

    自适应哈弗曼编码的完整Java实现,内有可执行文件和源代码,还有说明

    1. **哈弗曼编码原理**: 哈弗曼编码是一种基于字符频率的变长前缀编码,通过构建最小带权路径长度的二叉树(哈弗曼树),为每个字符分配唯一的路径,即编码。频率高的字符拥有较短的编码,频率低的字符编码较长,...

    深入理解字符编码

    ### 深入理解字符编码 #### 编码常识 **字符集与字符编码** - **定义**: 字符集(Charset)是指一组抽象字符的集合,涵盖了文字、符号等多种元素。例如,英文字符集包含了英文字母、数字及常用符号等。 - **作用*...

    java字符流练习-电话本管理系统

    Java字符流是Java IO系统的重要组成部分,主要用于处理文本数据。在这个名为"java字符流练习-电话本管理系统"的项目中,开发者使用了Java的字符流API来实现一个电话本管理的功能。电话本管理系统通常包括添加联系人...

    Java 正则表达式判断字符串是否包含中文

    #### 二、中文字符编码范围 中文字符在 Unicode 编码中的范围是从 `\u4e00` 到 `\u9fa5`。这个范围涵盖了汉字的大部分常用字符集,包括简体和繁体中文。因此,可以通过这个编码范围来编写正则表达式,用以识别和...

    Java实现哈夫曼编码和解码

    - 哈夫曼编码原理:根据字符频率构建最优编码 - 编码和解码算法:从二叉树生成编码表,从编码表解码回原始字符串 - 安全性考虑:可能需要添加校验机制以确保数据完整性 通过理解这些概念,并结合Java编程,可以实现...

Global site tag (gtag.js) - Google Analytics