原写于2010-10-05
一、编码基础知识
1.为什么要编码、解码
计算机存储的最小单位是“位bit”,存储的所有内容都是一串二进制的表示。但最小的存储单元是byte,内存的编址也是以字节为单位,大部分的计算机系统都是以字节为单位进行存储、计算、传输。从而必须有:字符(多字节表示)与字节的相互转换。
编码:字符转换为字节;解码:字节转化为字符。
2.常见基本字符集
- ASCII :只使用了一个8位字节中的低7位,总共是128个编码位。最早由美国制定,定义英文字符与二进制位之间的关系
- Iso8859-1:单字节编码,8位全部使用,涵盖了大多数的西欧文字。(Unicode的最开头256个字符编码和ISO-8859-1是一一对应)
- gb2312:ISO制定了ISO 2022标准,提供了七位与八位编码字符集的扩充方法的标准,gb2312是根据ISO 2022标准制定的2字节编
- gbk:2字节编码,是国家技术监督局1995年为中文Windows 95所制定的新的汉字内码规范
- gb18030:全称是《信息交换用汉字编码字符集》,是我国的强制标准(包含日韩等,支持单字节、双字节、4字节编码,中国大陆的标准)
字符集的概念:在确定的规则下,一个value与一个字符的对应关系
3.多字节与ascii关系
多字节编码,只是对中文及相关字符进行编码,可以认为是ascii的扩充。
gb2312规定:2字节编码,只使用每个字节的低7位,高位为0。结果:在计算机内部无法区分ascii码与gb码,出现“机内码(计算机内部表示汉字的编码),gb每个字节最高为置为1”。字符集依次增长的过程,向下兼容。
4.Unicode
UTF为UCS Transformation Format的缩写(深入了解:参考UCS的结构)。Unicode只是一个符号集,它只规定了符号的二进制代码,每一个符号都给予一个独一无二的编码,却没有规定这个二进制代码应该如何存储。常用的unicode实现方式有UTF-8和UTF-16。容纳全世界的编码,优点:中文的网页,在英文版的浏览器也能正常显示,不会乱码。
问题:汉字“严”的unicode是十六进制数4E25,两个字节。如何才能区别unicode和ascii,计算机怎么知道2个字节表示一个符号,而不是分别表示2个符号呢?
4.1 UTF-16:定长双字节
- 缺点:数据量增大,如果对于英文字符,增加2倍;属于ascii字符,高字节填补为0×00,在C里面是字符串的结尾,带来无数问题。
- 优点:直接表现字符编码的整数值,所以UTF-16是最直接的Unicode表示法。它是定长的,这大大简化了字符串的操作,Java语言就是用UTF-16格式将字符存储在内存中。
4.2 UTF-8:变长字节编码(1-6字节)
对于单字节的符号,字节的第一位设为0,后面7位为这个符号的unicode码。
对于n字节的符号(n>1),第一个字节的前n位都设为1,第n+1位设为0,后面字节的前两位一律设为10。剩余的二进制位,全部为这个符号的unicode码。
- 如果一个字节,最高位(第8位)为0,表示这是一个ASCII字符(00 – 7F)。可见,所有ASCII编码已经是UTF-8了。
- 如果一个字节,以11开头,连续的1的个数暗示这个字符的字节数,例如:110xxxxx代表它是双字节UTF-8字符的首字节。
- 如果一个字节,以10开始,表示它不是首字节,需要向前查找才能得到当前字符的首字节。
- ascii单字节编码,中文属于3字节范围。
5. 为什么乱码
乱码有很多种情形,但是万变不离其宗,就是“解码所用的charset和编码所用的charset不兼容”。
Unicode规定,编码时,碰到“看不懂”的字符,一律用“?(0x3F)”表示;解码时,发现“看不懂”的字节,一律用“�(0xFFFD)”表示。
二、Java编码问题
宝宝:分析Java中文乱码问题的根本原因,首先要了解这些中文字符的输入源,其次是了解这些字符被输出到用户浏览器经过了哪些转换和输出环节。
中文字符可以来源于:
1.程序内嵌的中文,源代码里直接写中文字符串。
2.外部读入的中文。
1. 程序内嵌中文:
Java源代码(.java)本身是一个文本文件,所以和读普通文本文件一样,编译器(javac)必须以字节流的方式读入文件内容,并以适当的编码转换为Unicode字符存储在Java字节码文件(.class)中。例如 :源代码文件中包含GBK编码的中文字符,则使用下面的命令编译:javac -encoding GBK MyClass.java,如果不指定-encoding参数,javac会使用JVM默认的编码(Java虚拟机取操作系统编码) 在中文Windows上,默认是GB18030,在英文Linux上,默认是ISO-8859-1。因此,如果文件是在英文Linux下编译而未指定-encoding,那么文件中的中文“我爱Alibaba”就会变成“ÎÒ°®Alibaba” 。
2. 外部读入的中文,如:数据库读入、文件读入、用户数据的提交。
以用户输入为例:
1.输入,结论如下
注:一般来说,URL只能使用英文字母、阿拉伯数字和某些标点符号。这是因为网络标准RFC 1738做了硬性规定:
只有字母和数字[0-9a-zA-Z]、一些特殊符号“$-_.+!*'(),”[不包括双引号]、以及某些保留字,才可以不经过编码直接用于URL,这意味着,如果URL中有汉字,就必须编码后使用。但是麻烦的是,RFC 1738没有规定具体的编码方法,而是交给应用程序(浏览器)自己决定。这导致“URL编码”成为了一个混乱的领域。
1. 网址路径的编码,用的是utf-8编码. (firefor&IE相同)
http://www.taobao.com/春节 %E6%98%A5%E8%8A%82
2. 直接在浏览器输入查询字符的编码,不同的浏览器有不同的处理.
http://www.taobao.com/?q=春节
chrome : %E6%98%A5%E8%8A%82
firefor(中文版): %B4%BA%BD%DA
3. GET和POST方法提交的编码,由网页的编码决定
4. Ajax调用的URL包含汉字, IE总是采用GB2312编码(操作系统的默认编码),而Firefox总是采用utf-8编码. (未验证)
2. 数据在内存中的编码
Java用unicode(实现unicode-16)编码,Java能够实现unicode与其它字符集之间的转换。比如: GBK的字节串d6 d0转换成utf8字节串e4 b8 ad的过程是:GBK bytes (解码) -> unicode (编码) -> UTF8 bytes(解码),而不是gbk -> utf-8。
3. 数据输出
3.1 Servlet输出:
字符流方式 response.getWriter(),用来输出文本类型的内容,如HTML和纯文本。 在调用response.getWriter()前,我们必须设置content type:response.setContentType("text/html; charset=GBK"); response.getWriter()通过content type中指定的字符编码来决定如何将字符流转换成字节流。
3.2 浏览器如何确定页面的字符编码
浏览器收到从WEB服务器返回的页面时:1.首先检查HTTP响应中指定的contentType,也就是servlet通过response.setContentType方法设置的值。如果content type中指定字符编码(例如text/html; charset=GBK),则使用这种方式解码这个页面;2.如果HTTP响应中没有指定字符集,那么浏览器会检查HTML页面中是否包含:<meta http-equiv="Content-Type" content="text/html; charset=GBK">如果找到,则使用这里指定的字符编码;3.如果既没有在HTTP响应中指定字符编码,也没有在HTML内容中指定字符编码,则浏览器根据一定的规则自动确定页面的字符编码(字符集探测)。例如,在英文环境中,浏览器会使用ISO-8859-1,简体中文环境中,则使用GBK。
三、总结:
分析Java中文乱码问题的根本原因,首先要了解这些中文字符的输入源,其次是了解这些字符被输出到用户浏览器经过了哪些转换和输出环节。 乱码有很多种情形,但是万变不离其宗,就是:解码所用的charset和编码所用的charset不兼容。
主要参考:
1.宝宝的文章<中文化和国际化问题浅析>
2.阮一峰的网络日志http://www.ruanyifeng.com/blog/2007/10/ascii_unicode_and_utf-8.html, http://www.ruanyifeng.com/blog/2010/02/url_encoding.html
相关推荐
总的来说,理解和掌握字符编码及转换对于开发健壮的J2EE应用至关重要。正确配置和使用字符编码过滤器,可以有效地防止由于编码不一致导致的乱码问题,提高用户体验。在实际项目中,应根据具体需求选择合适的字符编码...
通过深入研究和理解这个易语言字符编码转换源码,开发者不仅可以掌握字符编码的基本概念,还能学习到易语言的具体应用技巧,这对于开发涉及跨平台文本处理或需要与不同编码系统交互的项目非常有帮助。同时,这也是一...
理解并正确处理字符编码对于任何VB开发者来说都是必不可少的技能,特别是在处理跨平台或多语言应用时。确保在传递消息或数据时进行适当的编码转换,能够保证信息的准确无误,避免不必要的兼容性问题。
字符编码是计算机科学领域中的重要概念,用于将人类可读的字符转换为计算机可以处理的数字形式。在本文中,我们将深入...理解字符编码的重要性,以及掌握如何查询和使用这些编码,对于任何IT从业者来说都是必备技能。
文档中主要介绍了各类字符集以及相关的字符编码,字符的显示原理,从输入到显现的整个过程,程序中出现的乱码问题以及解决方案
字符集和字符编码是计算机处理文字的基础,它们...从简单的文本处理到复杂的软件开发,从本地化到全球化,都需要对字符编码有深入的理解。因此,深入学习并掌握字符集和字符编码的知识,对于IT专业人士来说至关重要。
本工具“中英文字符编码查询工具”专注于帮助用户快速查询中文和英文字符的编码,这对于开发者调试程序、处理文本数据或理解字符编码原理具有重要意义。 首先,我们来了解最基本的ASCII编码。ASCII(American ...
总结一下,"字符编码转换处理工具"是处理字符编码问题的强大助手,它支持从ANSI码到十六进制、二进制的转换,对于理解和调试涉及编码的问题非常有帮助。无论你是程序员、网页设计师,还是普通用户,这款工具都能让你...
本文将基于“工具-字符编码转换”的主题,深入探讨字符编码的概念、常见编码格式、字符编码转换工具以及如何进行实际操作。 字符编码是计算机表示和处理文字的一种方式,它将各种字符与二进制数字对应起来。常见的...
字符编码是计算机处理文本的关键技术,它决定了计算机如何理解、存储和显示各种语言的字符。在信息技术领域,正确理解和使用字符编码至关重要,因为不同的编码方式适用于不同的语言环境和应用场景。"字符编码查询...
工具如“StrParser 1.2”就是为了实现这种转换而设计的,它可以将文本在这些编码之间灵活切换,同时提供10进制和16进制的显示方式,便于开发者和用户理解和处理字符编码问题。 在实际应用中,了解并掌握这些字符...
通过理解ASCII、GB2312-80以及Unicode等不同的字符编码标准,我们可以更好地处理多语言环境下的文本数据。同时,掌握字符编码之间的转换方法也是必不可少的技能,这对于开发国际化应用程序至关重要。随着技术的发展...
总的来说,字符编码是计算机处理文本的关键,而《字符编码查询之星》作为一款专业的编码转换工具,不仅能够帮助用户解决实际问题,还能提高对字符编码的理解,是IT从业者和普通用户处理编码问题的得力助手。...
"完整版字符编码查看器"是一款实用工具,它可以帮助用户查看和理解各种字符编码格式,包括常见的ASCII、Unicode(如UTF-8、UTF-16)以及GB2312、GBK等简体中文编码。 首先,ASCII编码是最基础的字符编码,它包含了...
字符编码是计算机处理文本的关键,尤其在多语言环境中,正确的编码解决方案显得尤为重要。本文主要针对C++编程中遇到的乱码问题,从编码原理、Unicode的意义出发,详细讲解了四个典型场景下的乱码问题及其解决方案。...
本资源"中英文字符编码查询助手"是一个实用工具,旨在帮助用户快速查询和理解字符编码,尤其对于处理多语言环境中的文本问题非常有用。下面我们将深入探讨字符编码的相关知识。 1. **字符编码的基本概念**: - **...
字符编码定义了如何将文字、符号等字符转换成二进制形式,以便计算机理解和处理。本文将深入探讨字符与编码的概念、发展历史、程序中的应用,以及如何解决乱码问题和进行编码转换。 **一、字符与编码的概念** 字符...
字符编码决定了文本在不同语言环境中的显示方式,确保用户能够正确理解和阅读网页上的文字。本文将深入探讨字符编码的重要性、常见字符编码标准以及谷歌浏览器中如何利用字符编码插件来解决编码问题。 字符编码是...
字符编码与解码是计算机科学中的重要概念,尤其在处理文本数据时不可或缺。字符编码是将字符转换为二进制数的过程,以便计算机能够...在日常工作中,掌握这些知识能帮助我们更好地理解和处理与字符编码相关的各种问题。