LinuxSir.cn,穿越时空的Linuxsir!

 找回密码
 注册
搜索
热搜: shell linux mysql
查看: 12847|回复: 43

有关 utf8 字符集的讨论请进这里!

[复制链接]
发表于 2004-12-23 18:01:48 | 显示全部楼层 |阅读模式
1.locale等环境变量是有一个文件全局统管,还是shell一个 xserver一个 gtk一个。。。。。
2.把整个环境变量改成zh_CN.GB18030,就是改的和fc1一样会有什么后果??
3.国家强制标准是zh_CN.GB18030,大虾们从没考虑过utf-8现在和将来的兼容性问题吗??我们就这样忽视国家标准??
发表于 2004-12-23 19:42:21 | 显示全部楼层
在标准制定中从来都是业界指导国家,不是国家指导业界,假如没有开源的实现就不应当制定为标准——可惜这种话只好在外国去说,他们正是这样的规矩——也就是说,这些发行版会继续保留 GB18030 但是只把 utf-8 当作默认值,来应付中国的情况。windows 也是一样的
每个应用程序都有自己的环境变量,在不明白指定时会使用父进程的设置,最初的设置当然是从配置文件中获得的。比如 bash 在配置文件 /etc/profile.d/lang.sh 中读取 $HOME/.i18n 中的设置,另外在每次登录时都会读取 $HOME/.bashrc 中的设置。然后,这些设置在 bash 的子进程中生效
每个应用程序可以在内部处理不同的编码,例如浏览器可以查看不同编码的文档,编辑器 vi 和 OOo 也可以处理不同编码的文本,而 gnome-terminal 也能显示不同的编码——不过这是另一回事了
环境变量改成 GB18030 最坏的事情就是如果要临时使用其他语言比如英文,那么 GB18030 编码的文件名会显示为乱码。将来你不会再用其他语言吗?

每个应用程序的环境变量完全是独立的,这一点可以利用,比如在不同的应用程序中使用不同的输入法什么的,或者临时切换到另一种语言环境,不必修改系统设置,只要 export LC_ALL=zh_CN.XXXXXXX 就可以了
 楼主| 发表于 2004-12-23 22:10:43 | 显示全部楼层
1."环境变量改成 GB18030 最坏的事情就是如果要临时使用其他语言比如英文,那么 GB18030 编码的文件名会显示为乱码。将来你不会再用其他语言吗?"

这句话就是说utf-8可以包括各种文字编码,而gb18030只对汉字编码,所以遇到其它文字就乱码了??

2.“在不明白指定时会使用父进程的设置"

当我init 3时,startx后,shell是x的父进程。init 5时x没有父进程??对吗??

3.“比如 bash 在配置文件 /etc/profile.d/lang.sh 中读取 $HOME/.i18n 中的设置,另外在每次登录时都会读取 $HOME/.bashrc 中的设置。”

是说登录前是用i18n,登录后用各自帐户的??

3x!
 楼主| 发表于 2004-12-23 22:24:49 | 显示全部楼层
再问,locale的一个作用就是确定和分析编码,对吗?
比如,我用自身为utf-8的gedit写一个文档,里面的字符就是utf-8编码的
我用gedit 打开一个gb18030编码的文档,如果LC_SUPPORT中有gb18030就可以顺利打开,否则就有问题

是这样理解??
 楼主| 发表于 2004-12-23 22:34:36 | 显示全部楼层
请看这个:


按自己想法改的gftp
主要改了对中文的支持.
下载时会将ftp上的文件名编码(通常是gbk),
自动转换为你现在所用的locale!
上传时则会做相反的转换...

如果你使用的是UTF-8的locale,你就该明白为什么我这么做了
(大家所抱怨的linux文件上传到windows出现乱码,
windows文件下载下来文件名乱码...)

使用时设置一下Remote Character Sets: gbk

希望对大家有用...
我已经用了一段时间了

上传了两个文件
一个是rpm, 在FC3下编译的
另一个是源代码的patch


有这种必要吗??是不是只要让gftp的环境变量支持gbk就行了??(LC_SUPPORT=zh_CN.GBK????)
 楼主| 发表于 2004-12-24 12:06:17 | 显示全部楼层
一定要弄懂,顶一下
发表于 2004-12-24 12:55:38 | 显示全部楼层
LC_SUPPORT 不知道是做什么用处的,gedit 是从 gconf 中读取配置的,在这个位置/apps/gedit-2/preferences/encodings/auto_detected。如果这个配置中有 GB* 那么 gedit 就会自动判断编码。这个和 LC_* 没关系
gedit 可以保存的编码——这个和浏览器的例子类似,是程序可以处理的编码,这个和 LC_* 也没有关系
locale 变量很多,因此作用也很多,比如日期和时间格式,货币单位,字符编码,语言 (注意语言和字符编码是不同的),字典顺序及等价字符(类),数字格式…… 总之非常多
utf-8可以包括各种文字编码,而gb18030只对汉字编码,所以遇到其它文字就乱码了——这种说法有道理,不过不全对。gb18030 也包括其他字符的编码,但是——操那些语言的用户不会去用 gb18030,规范中这些内容就没什么用处了
除了 init,其他进程都会有父进程,只不过找起来比较麻烦罢了,因为父进程退出后就找不到了
bash 那个例子,我说的有问题。不能用 “登录”,只能用打开一个新会话,因为会话和登录是两回事。别追寻 “登录前” 是什么样子,那个和用户无关。那些配置文件都是在打开新会话之后起作用的
gftp 那个修改当然是有必要的, (向作者致敬!) 作者也说了 “当下载时会将ftp上的文件名编码(通常是 gbk ),自动转换为你现在所用的 locale,上传时则会做相反的转换,如果你使用的是 UTF-8 的 locale ,你就该明白为什么我这么做了……” LC_SUPPORT 在这里没什么用处。如果 locale 是 GB* 当然用不到这个布丁
当初我学了好久,才慢慢明白是怎么回事,所以你别着急。要区分问题的主要矛盾,究竟是应用程序受编码影响,还是应用程序要处理不同的编码。把后一种情况去掉,就发现剩下的是前一种,也就是父子进程关系了
发表于 2004-12-24 13:02:56 | 显示全部楼层

节选看过的一点材料,是关于编码的。关于 locale 的再找吧

节选自 FreeBSD China 的版面,不知道是不是真的权威说法
GB18030 和 WAPI 是不是一样的东西?
另外,用 UTF-8 一到六字节的变长编码,其实也不错

“本文是北京市科委组织的桌面Linux操作系统项目的专家组的专家孙卫先生在和我交流探
讨的电子邮件中向我介绍的有关汉字编码的部分内容,经孙卫先生同意,允许我发表在我
们的论坛里。再次向孙卫先生表示感谢!”

原文节选如下:


中国文字的历史是5千年,根据我们现在在文献记载可以看见的大约是20万个各种各样的字
.1949年,为了扫除文盲和普及文化,在50年代-60年代根据最常用的字进行了两个重要的规
范,一个是对文字的读音进行拼音化标准,原来是四角号码和注音.另一个就是对1千多个常
用字进行简化,加上常用的不能简化的字,推出了国家一级字库,大约是几千个字.这两项改
革使得中国大部分人走上了脱盲的道路.在70年代上,计算机要使用汉字,标准和规范都是外
国和台湾的, 实际上主要是外国的.80年代开始,个人计算机大量在中国使用,国家规定了G
B2312的标准,在CCDOS上开始使用.GB2312在字形上是采用的中国国家颁布的汉字字形,全部
是有拼音的,但是在编码上,为了保证计算机上的使用,采用的是ISO2022的编码法则.对于当
时,不同的国家,只有标准字符集和标准符号集在ISO2022中,不同国家的编码区域是完全一
样的,但是在各自的文字区域是复用的,即,如果安装了GB2312就无法兼容安装日本的标准编
码.在80年代末期和90年代初期,海峡两岸的交流越来越多,却出现了在计算机上文字互补兼
容的问题,在90年代初期,制定了一个GBK的规范,就是在大陆的6763字后面,增加BIG5里面的
15000汉字的部分.这个部分是字型与台湾的字型是一样的,但是编码仍然是ISO2022.同时8
0年代末期,国际上已经开始重视文化在计算机上的交流,提出了国际统一码的概念,就是在
一个编码体系里面容下全世界的文字.针对这个倡议,世界各国组织了 Unicode委员会,同时
也制定了一个新的编码标准,就是ISO10646编码.由于90年代初期,认识的局限性,中国没有
积极的参与这个活动,日本, 韩国在第一个标准里面占据了大量的码位,后来成立了Super
C.J.K小组进行协调,在这个标准里面,把大陆,台湾的字型都放在里面的话由中国人占据的
码位是20902个,含了所有的GB2312,GBK, BIG5的字型字.90年代末期,中国政府在此基础上
,对于部分字型进行了处理和规范,形成了GB13000.1的标准文件,字型略有不同,但是编码是
采用ISO10646的编码体系.目前在大陆的微软系统用字是ISO10646的20902个汉字.Unicode
和ISO10646在初期的理论基础是不同的,Unicode认为字符编码应该是变长的,而ISO10646却
认为字符编码是定长的,并且用2字节码就可以把世界上所有的文字解决完.UTF- 8,UTF-16
,UTF32就是在Unicode的理论上形成的计算机信息格式编码.在ISO10646的前面几个版本,是
可以用USC2,和UTF- 8进行处理的.但是,在90年代末期,中国向Unicode委员会又提交了6千
多个汉字,ISO10646的编码体系最大只能放65536个字符,无法满足东亚语言新提交的字符要
求,所以ISO10646从3.0开始进行扩充,在原有编码基础上,对于还未用满的区域进行了扩充
,拓展了一部分到4字节,这样 ISO10646的编码空间从65536到了150万字符的容量.所以在后
来的ISO10646标准都是采用了变长码的原则,完全与Unicode重合了.这样Unicode和ISO106
46变成了等同的关系,目前已经到4.0了,一共有71000汉字.在4.0中一共是3个部分,基本级
20902, 扩充A6千多个,扩充B4万5千多个.回过来,在中国进行WTO谈判时,某些政府官员自己
认为要反对文化入侵,对于外国进入中国的信息系统进行限制,在仓促之间推出了GB18030-
2000,这个标准在ISO10646的基本集的20902字是用ISO2022进行编码的,对于扩充A的字是采
用的四字节码.但是在计算机实现上,不能ISO2022和ISO10646混用,如何解决了?微软就在表
现层是GB18030-2000的,在底层是 ISO10646的,用UTF-8处理.所有的多国语言问题都是这样
处理啦.目前在Unix和Linux的处理是,把6千多个4字节变换成2字节,在表现层和底层都用I
SO2022的标准.新的Linux的内核和X-Windows都支持Unicode的,所以,我们计划在新的计划
中,变成和微软一样的处理方法,使得底层是统一编码的,表现层是可以多编码转换的关系.
因为扩充B的4万5千多字无法转换成2字节编码啦(65536限制),所以今年将发布的 GB18030
-2003的新的和扩充B等同的部分使得Linux和Unix将付出新的代价.建议FreeBSD处理时最好
采用和微软公司一样的方法.一次解决后,只需做翻译码表,而不需要动底层了.当时我是国
家图书馆的总工程师向信息产业部质疑为什么GB18030-2000是强制性的,如何解决多国语言
问题?如何参加国际交流?现在教育部语言文字委员会开始研究ISO10646/Unicode/GB13000
的问题,因为康熙字典有52000字,大约有40000多个在V4.0中,中华大字典有5万多个字都在V
4.0中,2004年开始的第二代身份证也采用的是71000汉字体系,所以Unicode 4.0和ISO1064
6标准将成为最简单的处理中文信息并与国际接轨的方式.GB13000就是与ISO10646全兼容的
标准,也从未废止过.
发表于 2004-12-24 13:30:19 | 显示全部楼层
从这段文字中可以了解很多事情,就是 UTF-8 是很不错的办法,字很全,并且所有人都可以接受
文中后半段建议像微软那样采用两层的方法,在文件写入文件系统中时对文件名进行编码转换,这个过程你是看不到的——这种办法适应了政府的要求,却带来了处理的负担,因为读出和写入都要处理。另外的坏处就是增加了工具的复杂程度,linux 中有很多处理文本的工具例如 grep,它们能处理 utf-8 那样的编码,据说不能处理 gb*,因为编码自身结构的原因。还有很多地方会遇到编码问题,例如应用程序源代码本身的编码——假如你和外国人合作,编码却不一样,你写的注释会在他那里变成一堆垃圾,甚至编译器都接受不了;另外还有网页的编码,假如你的网页要给外国人看,你会用 gb* 编码吗?他们会看到乱码的。所以现在的做法就是单一编码,不再理会政府了。已有的资料是没办法全部转换的,例如最简单的,ftp 上的文件,还有 mp3 的 id3 标签编码,都是不可能完全适应新情况的,不过它们终究会失效,或者应用程序有了处理多种编码的能力。典型的例子是 perl 解释器,还有上面 gftp 的布丁

至于 locale,似乎没什么再详细的文档,因为它的规则本来就那么简单。linuxforum CMPP 有翻译好的手册页,可以看一看
发表于 2004-12-24 13:48:20 | 显示全部楼层

再转载两段。后一段很多是误导

zz:linuxforum:java源代码中常量字符串的编码处理
wz-i-like-linux
(journeyman)
06/13/03 21:29

Re: Java&JSP跨平台中文处理的问题 [re: baisha]
回复

这样吧,我看你已经被大家的回复彻底搞迷糊了,不如我来给你简单解释一下。
首先,java的中文问题出现在很多场合内。每种场合使用不同的处理方法。你这里想搞清
楚的是“在java源代码文件中的常量字符串引号内出现的中文字符的运行时显示”的问题

ok,那么我们就来看看javac如何编译该字符串。首先,javac看命令行中有没有用-encod
ing参数指定一个字符集,没有,则用系统环境中指定的字符集。接下来javac开始解释源
码文件,遇到多字节的字符,就用前面确定的字符集编码来解释,并转换为unicode,写入
.class 的字节码文件里面。
好了,下面我们要运行这个class文件了,jvm启动后读入class字节码,那些个中文字符串
都以unicode表示,这没什么可说的,在哪都一样(平台无关的)。下面可能需要输出这个字
符串到其它的应用程序了:控制台/文件/socket等等等等....这样jvm首先要检查操作系统
的 encoding(注意,jvm从字节码里面完全不知道这些字符串是什么编码的,全是unicode
),然后按该encoding来解释这些 unicode码到操作系统的encoding。当然,对于特殊的环
境jvm也许不去检查操作系统的encoding,而是从环境变量里面读,这样你就可以控制jvm
执行时的目的encoding了。
最后一步,如果你的操作系统的(或目的)encoding与真实的encoding一致(或具有兼容关系
),那么你将看到正确的字符串,如果你不一致,你会看到什么?对了,是问号。

所以“在 Linux 操作系统上就是ISO-8859-1”是不对的,关键是环境变量LANG是怎么设置
的,以及有没有显式地使用-encoding参数。

其实如果你编译和运行如果在同一个操作系统上运行的话,输出是绝对不会有问题的。那
么你的第四个问题是怎么产生的呢?很简单,虚拟机运行时输出的字符串是100%正确的,
可惜你的linux系统没有中文显示支持,所以你看到了乱码(不是问号,问号代表遇到了不
认识的字符),而从远程登录时,这些码被正确地显示了出来,这是因为你的远程系统具有
中文显示支持。

明白了吗?



=============
提问的是一个新手。所有的新手都会被编码问题困住。windows 从来没有让用户体会过什
么叫做多语言版本的软件,而 linux 是不分语言和民族的。这是 GPL 中“禁止任何形式
的区分对待”(无歧视) 原则的体现。言归正传,编码问题,在 linux 中,在 perl 脚本
语言中都困扰过我。现在又是 java 的编码问题--以前看着用 java 的人为这些头疼,
想不到现在自己也要处理这些了。
linux 中对常量字符串的处理和 c/c++ 中的处理方法显然是一致的,因为 linux 的结构
限定了这个样子。对于 c/c++ 的中文处理,没有谁会提出什么意见,因为 c/c++ 程序的
开发环境和运行环境一般是一致的 (编码都是一样的),编译器不会改变字符串的编码。因
此,大家在 dos 时代只有 “机内码” 概念,字符串只有一种可能的编码。要将一串二进
制的数据识别成字符,需要应用程序自行处理。现在的 c/c++ 有了 wchar_t 类型,可以
保存多字节的数据了,但是具体保存的数据是哪种编码,似乎没有规定。
在 linux 环境中,一般需要定义一些很重要的变量,统称为 locales。这些变量包括 LC
_CTYPE, LC_TIME, LC_NUMERIC, LC_COLLATE, LC_MONEY, LC_PAPER, LC_MESSAGES,
LC_ALL, LANG。按照字面意思,它们分别是字符编码,时间格式,数字,字典顺序,货币单位
,纸型, 应用程序界面语言。LANG 是统称,但是优先级比其他都低。LC_ALL 也是统称,
但是优先级比其他都高。有了这些变量,整个系统的语言环境就确定下来了。变量的值都
是这样:"zh_CN.GB18030", 含义也很明白,zh 是中文,CN 是简体中文,GB* 是编码。

很多程序是根据 locales 来决定自己的行为的。例如输入法,如果 LC_CTYPE 是英文(en
_US.ISO8859-1)时,也就是当前语言环境中根本没有中文的字符,仅仅有英文字符,那么
想输入中文就不大可能了。当然,LC_CTYPE=en_US.UTF-8 时,虽然英文中没有中文字符(
废话!),但是编码 UTF-8 中包含中文字符,所以这时仍然可以显示中文的内容。另外的
例子,几乎所有程序的界面都是根据 locales 中 LC_MESSAGES 的值来显示提示信息的,
只要修改这个变量,那么应用程序就变成了 “中文版”,“日文版”....
比较让人想不通的是为什么 mount 程序不是根据 locales 来决定自己的行为--每次挂
载磁盘,都需要设置参数,才能看到正确的中文。事实上, mount 不是一个应用程序。它
相当于是用来修改内核变量的。一个应用程序要想使用 locales 变量,就必须在启动这个
应用程序之前设置它的值。而内核挂载磁盘时的默认编码,在内核启动以后就无法再改变
了。这是在 linux 中推行统一编码的重要原因。由于 linux 厂商生产的版本中,内核只
有一个,从而只能有一种默认编码。在中国,redflag 等厂商可以在生产时调节内核默认
参数为 GB2312,但是这种产品是不能卖到其他国家的。同样,redhat 等等国外厂商为了
支持英文、法文、俄文等等各种语言,将内核默认参数调节成了 ISO8859-1。这样的产品
在中国使用时,就需要在 mount 时设置很多的参数,非常麻烦。目前的趋势是这些国外厂
商将内核默认编码调节为 UTF-8,从而做到编码统一。这样做给中国用户带来的问题是一
定要使用 UTF-8 作为语言环境,这和国家标准冲突很大。
perl 中的编码问题,如果程序仅仅在自己的机器上运行,那么和 c/c++ 也是一样的。用
户/开发者 根本不必考虑这些编码转换问题。但是,如果一个程序要在另一种语言环境中
运行,就应当在命令行指定源文件的编码。要不然,常量字符串就无法识别了。python 也
是这样。perl 做得比较好,任何语言都可以用作变量名/函数名,源程序可以用任何编码
。而 python 只能用英文做变量名。期待 python 做得和 perl 一样好。
perl 源程序的编码其实只在命令行加一个选项指定一下就好。比较复杂的就是将它显示出
来。更复杂的就是将它存储起来。
显示问题,只要用原文中的第四个问题就可以说明白了:“虚拟机运行时输出的字符串是
100%正确的,可惜你的linux 系统没有中文显示支持,所以你看到了乱码(不是问号,问号
代表遇到了不认识的字符),而从远程登录时,这些码被正确地显示了出来,这是因为你的
远程系统具有中文显示支持。 ”。linux 中大多数编码问题都应当用这条原则来解释。例
如,国内大多数 ftp 的中文目录/文件名编码是 GB2312,但是我的 linux 语言环境是 z
h_CN.UTF-8,那么就没办法访问这个 ftp,除非暂时修改我的 locales
存储时的编码一般都需要转换了。设想你的程序同时被很多人使用,有的编码是 GB, 有
的编码是 UTF-8, 有的编码是 JIS, 还有的是 ISO8859-1。他们都访问同一个数据库,
将自己的信息保存同一个文件中。那么,你是不是应该处理一下他们的输入,把输入转换
成同一个编码呢?如果已经转成了同一个编码,那么下次再读取出来,show 给那些用户时
,应该用什么编码才好呢?是不是应该再转换一次?第一次转换时,目标编码是你控制的
,但是源编码一定是你想象中的那一种吗?第二次转换时,应该转换成什么目标编码才好
呢?假如判断错误,就会给用户显示一大堆乱码。google 解决这个问题是用 UTF-8 实现
的,也就是强制用户使用 UTF-8 编码。1.)即使用户存心捣乱,输入其他编码的搜索目标
,也不会产生太大问题。2.)各种浏览器一般都支持 UTF-8 ,那么输出也不是什么大问题
。只要浏览器可以自动识别编码,用户就不会看到乱码。猜测用户编码的做法是好心办坏
事。
小百合的编码是 GB2312。如果用户故意上传一个文件,文件名是其他编码,那么很有可能
这个文件会保留在系统中,永远删不掉了。当然,这和 GB* 编码没有关系,只是因为百合
不能正确判断用户的输入。假如用 UTF-8 编码来查看百合的页面,然后发一篇文章,那么
这篇文章在正常的 GB2312 编码中查看时就一定是乱码,并且很有可能删不掉。试一试?

经验之谈,有错误的话不负任何责任。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复 返回顶部 返回列表