`
tballan
  • 浏览: 8263 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
最近访客 更多访客>>
社区版块
存档分类
最新评论

抽丝剥茧之一:编码与解码

阅读更多

 

0. 卷首语

 

编码:将“源对象内容”按照一种“标准”转换为“符合这种标准格式内容”的方法。
解码:和编码对应的,它使用和编码相同的标准将编码内容还原为最初的对象内容。

 

如果某个文件是用A编码方式编码的,但是打开时按B编码方式打开,就会显示乱码。

关键在于:用正确的编码方式打开文件以显示出正确的文件内容

 

1. 编码目的

 

  • 安全角度:数据加密
  • 传输角度:信息交换
  • 空间角度:文件压缩

2. 编码方式

 

  • ANSI编码
    • 美国国家标准协会(ANSI)发布
    • 前127位为英文字符,使用ASCII字符集实现
    • 后127位为扩展字符,根据操作系统判定
      • 简体中文使用GB2312字符集实现
      • 繁体中文编码使用BIG5字符集实现
      • 西欧字符编码使用ISO-8859-1字符集实现
      • ……
  • UNICODE编码
    • 国际标准化组织(ISO)发布
    • 引入原因:8bit的ANSI编码只能表示256种字符,表示26个英文字母是绰绰有余的,但是表示简繁体汉字,韩国语等有着成千上万个字符的非西方字符肯定就不够了,正是如此才引入了UNICODE标准。
    • 默认实现方式:所有的字符都会使用2个字节进行存储,英文字符也不例外
    • 默认实现指的是:UTF-16 / UTF-16LE / UCS-2 little endian / unicode little endian
    • 实现方式
      • UTF-8:以8位=1字节为单位,兼容ASCII,根据内容以1-4字节变长存储,例如英文1个字节,汉字3个字节
      • UTF-16 / UCS-2:以16位=2字节为单位,不兼容ASCII,定长2字节,无论中英文
      • UTF-32 / UCS-4:以32位=4字节为单位,不兼容ASCII,定长4字节,无论中英文
    • 字节序
      • CPU默认不同,intel/amd默认little endian,motorola/apple/ibm默认big endian
      • little endian:把低字节存放在内存的低位,把高字节存放在内存的高位
      • big endian:把低字节村房子内存的高位,把高字节存放在内存的低位
      • 可以与UTF-16、UTF-32组合,根据CPU默认不同
      • 简称:little endian = LE;big endian = BE
      • 组合简称:UTF-16=UTF-16LE;UTF-16BE;UTF-32=UTF-32LE;UTF-32BE
  • ISO-8859-1/LATIN-1编码
    • 前127位为英文字符,使用ASCII字符集实现
    • 后127位为扩展字符,使用ISO-8859-1字符集(法语、西班牙语和德语之类的西欧语言)实现
  • GBK编码
    • 前127位为英文字符,使用ASCII字符集实现
    • 后127位为扩展字符,使用GBK字符集(简体中文)实现

3. 编码实现——字符集

  • ASCII字符集
    • 美国信息交换标准字符集
    • 以单字节存放英文字符,以双字节存放中文等字符
    • strlen(英文)=1;strlen(中文)=2
    • 前127位为英文字符,后127位为扩展字
  • DBCS字符集组
    • 双字节简体中文字符集
    • 一个汉字算两个英文字符!
    • 前127位为英文字符(半角),后127位两两组合为中文字符(全角)
    • 包括以下四种中文字符集,在后127位里做了下文章
      • GB2312:ASCII的简体中文扩展字符集
      • BIG5:ASCII的繁体中文扩展字符集
      • GBK:ASCII的中文扩展字符集,包括了所有的简体和繁体,
      • GB18030:GBK+CJK的中文扩展字符集,少数民族的字都进来了,日韩的字进来了,准确点说,它是以ASCII+UNICODE共同为基础的杂种字符集

    C#中默认的是UTF-16,因不兼容ASCII,所以在处理C#字符串的时候只能是byte,stream等方式去处理

    XML中默认的是UTF-8

    系统输入里ALT + 数字 = 汉字,根据UNICODE显示

    char(ansi) / nchar(unicode),因此strlen(char["xx张oo"]) = 6;strlen(nchar["xx张oo"]) = 5

    系统同时支持ANSI和UNICODE,文件创建时默认为ANSI,但在重新打开时会只能判定编码后显示

    而当你新建一个文本文件时,记事本的编码默认是ANSI, 如果你在ANSI的编码输入汉字,那么他实际就是GB系列的编码方式,在这种编码下,"联通"的内码是:
    c1 1100 0001
    aa 1010 1010
    cd 1100 1101
    a8 1010 1000
        注意到了吗?第一二个字节、第三四个字节的起始部分的都是"110"和"10",正好与UTF8规则里的两字节模板是一致的,于是再次打开记事本时,记事本就误认为这是一个UTF8编码的文件,让我们把第一个字节的110和第二个字节的10去掉,我们就得到了"00001 101010",再把各位对齐,补上前导的0,就得到了"0000 0000 0110 1010",不好意思,这是UNICODE的006A,也就是小写的字母"j",而之后的两字节用UTF8解码之后是0368,这个字符什么也不是。这就是只有"联通"两个字的文件没有办法在记事本里正常显示的原因。
    而如果你在"联通"之后多输入几个字,其他的字的编码不见得又恰好是110和10开始的字节,这样再次打开时,记事本就不会坚持这是一个utf8编码的文件,而会用ANSI的方式解读之,这时乱码又不出现了。

     

     

    2. 在系统(Windows/Linux)中新建文件的编码

    3. 在Java中写文件的编码(默认为java文件编码,网络上的文章是错的!)

    http://elf8848.iteye.com/blog/271742

    4. Servlet的编解码

    5. JSP的编码与解码

    http://hi.baidu.com/amwaisn/blog/item/7e981597ff71ee47d1135e88.html

    http://wenku.baidu.com/view/b675f311f18583d049645947.html

    http://msq.iteye.com/blog/101050

    6. Http的编解码

    7. URL的编解码

     

    分享到:
    评论

    相关推荐

    Global site tag (gtag.js) - Google Analytics