BBYR Achieve
返回信息流
这是一条镜像帖。来源:北邮人论坛 / soft-design / #27689同步于 2008/7/3
该镜像源已超过 30 天没有更新,可能在源站已被删除。
SoftDesign机器人发帖

[讨论]炒冷饭,谈中文处理

jerrytian
2008/7/3镜像同步4 回复
国际化支持,多语言,本地化,这些概念的背后都是"字符串"的内容和相关操作是否是多字节安全的. 字符串编码存在的本质是计算机只能存储和处理"数字",所以人类沟通中使用的字符串必须转化为"数字串"的方式才能被计算机处理或者在网络上传输.将字符串中的每个字符转换到特定数字组合的规则就是字符编码. ascii编码是最常见的用来编码英文字符的单字节编码方式,对于字符串"hello",使用ascii编码后的"数字串"用十进制表示就是[104,101,108,108,111]. 对于中文,日文,韩文等亚洲文字,一个字节能表示的最大数值已经无法容纳映射后的用来代表某个字符的数值,所以多字节编码方式就成了必然,中文的GB2312,GBK,GB18030编码标准的制定就是为了完成这个任务.然而,使用多字节存储一个数值的时候,又会遇到一个问题,就是字节存储的顺序(BIG ENDIAN/BE和LITTLE ENDIAN/LE的由来,这点上,不仅仅在存储字符编码时会遇到,任何用到多字节存储的时候都会碰到这个问题).对于GB2312,GBK,GB18030,不仅仅一个中文字符映射到的数值是确定的,并且这个数值字节存储的顺序也是确定的. 到这里,可以看出,对于中文的处理,有两个步骤: A.将一个汉字映射到一个数值; B.将这个数值按照某种约定的字节存储顺序存储,操作,传输. 这时,再引入国际标准的字符编码UNICODE.对于步骤A,UNICODE编码已经包括所有人类使用中的字符;对于步骤B,UNICODE标准也定义了多种方法,UTF-8,UTF-16,UCS-2是常见的几种. 编码的概念暂时到这里,剩下不得不提的就是应用程序在处理多字节字符时的编码问题.同样,两个司空见惯的操作: 1. 用文本编辑器(纯文本)输入中文保存到文本文件中; 2. 在终端(windows的cmd窗口, *nix上的各种terminal)将文本文件的内容dump出来; 对于中文windows操作系统(内码使用UNICODE)上,中文字符可以很顺利的在编辑器和终端中显示出来.理所当然的背后就是操作系统已经为文本编辑器和终端提供了足够的字符编码信息:文本文件将使用GBK编码方式存储中文字符;终端可以假设接收到的字节流是GBK编码的字符串. 这里的GBK编码方式(windows操作系统内部的codepage序号为936,所以又经常可以看到cp936的中文编码名称)就是操作系统默认字符编码. 然而网络服务程序(例如,HTTP服务器)无法为客户端OS的默认字符编码做任何假设,所以最好的方法就是在将文本内容的字节流传输给客户端之前,先通知客户端字节流将采用的字符编码方式.这就是HTTP报文header里,"Content-Type"字段中"charset"的作用(Content-Type: text/html;charset=gb2312).出现乱码的页面,几乎可以确定要么是缺失该信息,要么就是该信息错误. 最后,几行代码,描述一下Java,Python,Ruby的字符编码转换API,方便日后查阅. *注意,源代码文件都使用utf-8方式存储,操作系统默认编码为GBK. Java: String s = "你好"; byte[] b1 = s.getBytes("utf-8"); byte[] b2 = s.getBytes("GBK"); s = new String(b1, "utf-8");//OK! 等效new String(b2, "GBK") System.out.write(b1);//向终端直接写字节流.乱码! System.out.write(b2);//OK! 等效System.out.print(s) Python: # coding=utf8 s = u"你好" sys.stdout.write(s.encode("GBK"))//OK! 等效print s sys.stdout.write(s.encode("utf-8"))//乱码! Ruby: require 'iconv' s = "你好" puts s//乱码! puts Iconv.conv("GBK", "UTF-8", s)//OK! php应该也是提供iconv族的函数提供支持. etc...
订阅后,新回复会通过你的通知中心匿名送达。
4 条回复
wks机器人#1 · 2008/7/3
字符编码到现在为止都是很头疼的问题。 Python3.0会像Java一样严格区分bytes和str Ruby2也将加入本地Unicode字符串支持。
jerrytian机器人#2 · 2008/7/3
【 在 wks 的大作中提到: 】 : 字符编码到现在为止都是很头疼的问题。 : Python3.0会像Java一样严格区分bytes和str : Ruby2也将加入本地Unicode字符串支持。 python的支持算不错,和java对比可以接受. ruby的估计最原始(各种字符串操作都是针对单字节的),弄的rails自己专门重新定义了string的行为,增加了utf8支持.网上也是吵的一塌糊涂,另外jruby也整的非常尴尬.
TimNew机器人#3 · 2008/7/3
说起来,想起第一次用C#写那个传说中的什么学生信息管理系统的时候~嗯~发现死活都不支持中文~因为偶不知道有Encoding这个类~更不知道这鸟类居然是放在System.Text下面的~更不知道Encoding原来有个静态实例叫做Encoding.Default~~(当年用的好像是.net 1.1 + VS.net 2003,Class的模板默认没有using System.Text;~囧) .net 中似乎不用担心编码问题,因为 System.Char != System.Byte,System.Char 是记录编码的~ 说到这,有会引出一个典故~HopLee 老师著名的信息论课上,曾经交过一个BT的HuffmanCodec~当时不知道System.Char是表示一个字符(包括中文字符),偶的HuffmanTree的Node是用Char保存的~ 某次在给某人演示,顺手扔了篇丫丫小说进去生成字典,发现生成的编码字典文件居然有10多K~打开一看~发现每个汉字一个编码~囧~ 最后~ .net char[] 和 byte[] 可以用Encoding类实例的GetBytes()和GetString互转~
jingle机器人#4 · 2008/7/5
不错,以前也对字符集和编码很犯迷糊。我也共享点好东东,以前Intern Training时的ppt,关于Globalization的,可以参考下,有助于建立对字符集编码等相关的基础知识。 主要包括 Globalization(G11N) 的概念; Locale; Character Set and Encoding; Unicode Encoding and Java; BiDi; 这个很有意思,一般接触阿拉伯等语言时才会遇到。 【 在 jerrytian 的大作中提到: 】 : 国际化支持,多语言,本地化,这些概念的背后都是"字符串"的内容和相关操作是否是多字节安全的. : 字符串编码存在的本质是计算机只能存储和处理"数字",所以人类沟通中使用的字符串必须转化为"数字串"的方式才能被计算机处理或者在网络上传输.将字符串中的每个字符转换到特定数字组合的规则就是字符编码. : ascii编码是最常见的用来编码英文字符的单字节编码方式,对于字符串"hello",使用ascii编码后的"数字串"用十进制表示就是[104,101,108,108,111]. : ................... 附件(555KB) G11NIntroduction[1].pdf