转载:http://www.iteye.com/article/31860
字符串编码(charset, encoding/decoding)问题原理
编码问题很重要,关于编码问题的文章也很多。我本来没有兴趣重复这个主题。
一个朋友问我有没有比较好的编码介绍文章。我记得以前看过几篇很不错的,但是当时搜索到的时候,就比较费劲,一时想不起来。于是,我就说,我攒一篇好了。
---------------------------------------
编码无处不在。Database, file, editor, IDE, compiler, browser。
代码(比如java, jsp, asp, php, python, ruby etc)里面的字符串比较麻烦,涉及到editor, compiler, interpreter等等。
所以,我的做法是,从来不在代码里面直接写字符串资源,尤其是双字节编码的字符串资源。
都是把字符串资源分离到一个单独的资源文件里面。这样,只需要照管这个文件的编码就够了。
需要注意的一点是,文件里面、数据库里面、网络传输需要的数据,都是byte[]。
以下的讨论,不涉及代码里面的字符串编码问题。只讨论系统运行起来之后,各部分之间的编码问题。
先说Java。
JVM里面的任何字符串资源都是Unicode,就是说,任何String类型的数据都是Unicode编码。没有例外。既然只有一种编码,那么,我们可以这么说,JVM里面的String是不带编码的。String相当于 char[]。
JVM里面的 byte[] 数据是带编码的。比如,Big5,GBK,GB2312,UTF-8之类的。
一个GBK编码的byte[] 转换成 String,其实就是从GBK编码向Unicode编码转换。
一个String转换成一个Big5编码的byte[],其实就是从Unicode编码向Big5编码转换。
所以,Unicode是所有编码转换的中间介质。所有的编码都有一个转换器可以转换到Unicode,而Unicode也可以转换到其他所有的编码。这样构成了一个总线结构。
比如,如果总共有10种编码,那么只需要 10 + 10 = 20个转换器就够了。如果要是两两直接转换,那么,需要的转换器数量是一个组合数字,需要90个转换器。
一个系统的不同部分,都有自己的编码。比如,数据库,文件,JVM,浏览器这4个部分。
在这些部分之间数据交换的地方,就会出现编码问题。比如,数据库和JVM之间,文件和JVM之间,浏览器和JVM之间。这些问题的原理都是相通的。
编码问题最容易处理的地方是文件和JVM之间。文件IO API带有encoding 参数,请自行查阅。
最不容易出现编码问题的地方是数据库和JVM之间。这应该是数据库JDBC连接的基本功能。本文不专门进行讨论。
最容易出问题的地方是浏览器和服务器JVM之间(其实,代码里面的字符串更容易出问题,不过,我已经事先声明,本文不讨论代码中的字符串编码)。下面主要讨论这块浏览器和服务器JVM之间的编码问题。
我们把浏览器编码叫做 Browser_Charset,把JVM编码叫做JVM_Charset(通常等于服务器系统编码)。
当浏览器的数据过来的时候,是一个带有Browser_Charset的byte[]。
如果用户处理程序需要一个String类型的数据,那么JVM会好心好意地把这个byte[]转换成String。使用的转换器是 JVM_Charset -> Unicode。
注意,如果这个时候,Browser_Charset 和 JVM_Charset并不相等。那么,这个自动转换是错误的。
为了弥补这个错误。我们需要做两步工作。
(1) Unicode -> JVM_Charset,把这个String 转换回到原来的 byte[]。
(2) Browser_Charset -> Unicode,把这个还原的byte[]转换成 String。
这个效果,和直接从HTTP Request取得byte[],然后执行 (2) Browser_Charset -> Unicode 的效果是一样的。
如果在Request里面设置了CharacterEncoding,那么POST Data参数就不需要自己手工转换了,web server的自动转换就是正确的。URL的参数编码还涉及到URL编码,需要考虑的问题多一些,没有这么简单。
JVM把数据发到浏览器的时候。也需要考虑编码问题。可以在Response里面设置。另外,HTML Meta Header里面也可以设置编码,提醒Browser选择正确编码。
有些语言的VM或者解释器的字符串编码可能不同。比如,Ruby。不过,编码转换原理都是一样的。
That is all.
分享到:
相关推荐
### JSON编码与解码示例详解 #### 一、引言 JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,在Web应用中被广泛使用。它基于JavaScript的一个子集,易于人阅读和编写,同时也易于机器解析和生成。...
**算术编码原理** 算术编码的核心思想是将数据的概率分布转化为一个连续的编码区间。首先,对输入数据的概率模型进行估计,然后将每个可能的符号映射到一个概率区间。在编码过程中,不断更新区间,直到整个消息被...
在文件《Reed-Solomon Encoding and Decoding.pdf》中,作者León van de Pavert详细阐述了Reed-Solomon编码和解码的机制,并特别关注其在检测和纠正突发错误中的应用。此外,文件中还提到了交错(cross-...
URLexam是一个Web开发工具,可将文本编码为url编码的字符串,然后将url编码的字符串解码为纯文本。
根据给定文件的信息,我们可以提炼出与“RS编码与解码”...通过对这些细节的深入分析,我们可以更好地理解RS编码的工作原理及其实际应用。RS编码作为一种强大的纠错编码技术,在现代通信和数据存储领域发挥着重要作用。
1. 霍夫曼编码:霍夫曼编码是基于字符出现频率的前缀编码,具有更频繁的字符具有更短的编码长度,以此提高压缩效率。它通过构造霍夫曼树来生成编码。在MATLAB中,首先需要统计输入数据(8位或16位无符号整数)的频率...
卷积编码解码(Convolutional Encoding and Decoding)是一种在通信系统和数据存储中广泛使用的错误检测和纠正技术。这种编码方式通过引入冗余信息,增强了数据的鲁棒性,使得在传输或存储过程中即使有少量错误,也...
Huffman编码是基于字符频率的变长编码,对于不同频率的字符分配不同的位数,而LZW编码则是通过建立词汇表来压缩数据,特别适合于有重复模式的数据。 总的来说,零长编解码是数据压缩的一个基础环节,尤其适用于包含...
6. **生成编码字符串**:将转换后的字符连接成一个字符串。 解码过程则是编码的逆向操作: 1. **读取Base64字符串**:首先,读取Base64编码的字符串。 2. **检查和处理填充**:识别并去除末尾的`=`字符,这些表示...
标题“C and MATLAB implementation for Polar encoding and decoding.zip”指出,这个压缩包包含了Polar编码与解码的C语言和MATLAB实现。C语言是一种底层编程语言,适合编写效率要求高的编码和解码算法;而MATLAB则...
3、编码(Encoding):根据编码表对输入的字符串进行编码,并将编码后的字符串输出。 4、译码(Decoding):利用已经建好的哈夫曼树对编码后的字符串进行译码,并输出译码结果。 5、打印(Print):以直观的方式打印...
Bcg729 is an open source implementation of both an encoder and decoder for the ITU G729 Annex ... libbcg729 supports concurrent channel encoding/decoding for multi-call applications such as conferencing.
npm i encoding2decoding 编码方式 const { encode } = require ( 'encoding2decoding' ) ; encode ( 'abc' ) ; // Returns 101112 解码 const { decode } = require ( 'encoding2decoding' ) ; decode ( '101112' )...
1. **JSON编码**:将C语言中的数据结构(如结构体、数组等)转换为JSON格式的字符串。这在需要将数据发送到服务器或存储为文本文件时非常有用。 2. **JSON解码**:解析JSON字符串并将其转换回C语言的数据结构。这...
Ralf Junker先生写的Mime(64Base)EnCoding/DeCoding函数,太NB了!
3、 编码(Encoding):根据编码表对输入的字符串进行编码,并将编码后的字符串输出。 4、 译码(Decoding):利用已经建好的赫夫曼树对编码后的字符串进行译码,并输出译码结果。 5、 计算输入的字符串编码前和编码后的...
立体声编码/解码和双声道库libspatialaudio是一个开放源代码和跨平台的C ++库,用于Ambisonic编码和解码,过滤和双耳渲染。 它的目标是在从耳机到经典扬声器的多种环境中渲染高阶Ambisonic ( HOA )和VR / 3D音频...
3、 编码(Encoding):根据编码表对输入的字符串进行编码,并将编码后的字符串输出。 4、 译码(Decoding):利用已经建好的赫夫曼树对编码后的字符串进行译码,并输出译码结果。 5、 打印(Print):以直观的方式打印...