解决了Erlang的UTF-8转Unicode中文显示问题
来源:互联网 发布:淘宝香港订单怎么发货 编辑:程序博客网 时间:2024/06/05 01:17
最近想用Erlang新版本R14B下的wxErlang做点事情,却又遭遇Unicode困扰。没想到,很快就彻底弄清了问题的原因,找到了解决之道。
Erlang能够处理Unicode,是从版本R13A开始的。不过,经过中间7、8个版本,直到目前的R14B03,Erlang只能在werl.exe开启的shell中,把UTF-8多字节编码,解析成双字节构成的单一Unicode字符。而至少在R13A和R13B中,由erlc.exe编译非ASCII字符时,生成的UTF-8存在很大问题,甚至让人怀疑是假的。
发现这个问题,是对R13B测试的结果。据此,我写了《Erlang 中文简体字 GB2312 转 Unicode 的办法》。这两天,又发现了更为确凿的证据。
打开R13B的wxErlang例程sudoku_gui.erl,把函数create_window() 的第一行
Frame = wxFrame:new(wx:null(), -1, "Sudoku", []),
替换成以下内容:
Bin2 = unicode:characters_to_binary("中文窗口", utf8),
L2 = unicode:characters_to_list(Bin2),
gb2u:start(),
U = gb2u:get_unicode(L2,[]),
Frame = wxFrame:new(wx:null(), -1, U, []),
这里的L2本应是UTF-8,实际上却是GB2312。模块gb2u.erl,正是根据GB2312检索对应Unicode的。
目前的R14B已经彻底纠正了这个问题,编译模块时,即使不显式调用unicode库函数,非ASCII码的数据,也会自动编译成UTF-8。于是,我写的那个gb2u.erl,只能用于R13A和R13B这两个版本,在其他版本没有用武之地,它不能根据UTF-8找出对应的Unicode。
怎么办呢?反复查看琢磨Erlang和Python中UTF-8数据的格式,终于看出了规律,GB2312的汉字转成UTF-8时,绝大多数是3个字节。把gb2u.erl稍做改动,有了下面的程序。
def all_gb2312():
s = '''-module(utf82u).
-export([start/0,utf82unicode/2]).
utf82unicode([],U) ->
lists:reverse(U);
utf82unicode([A|T],U) when A < 128 ->
utf82unicode(T,[A|U]);
utf82unicode([A,B,C|Z],U) ->
H = get({A,B,C}),
utf82unicode(Z,[H|U]).
start() ->\n'''
f = open('utf82u.erl','w')
f.write(s)
for row in range(161,248):
if row > 169 and row < 176:
continue
for col in range(161,255):
ch1 = chr(row)
ch2 = chr(col)
w = ch1+ch2
try:
utf8 = w.encode('utf8')
uc = utf8.decode('utf8')
except:
continue
s='put({%s,%s,%s},%s),\n'%(
ord(utf8[0]),ord(utf8[1]),ord(utf8[2]),ord(uc))
f.write(s)
f.close()
上面Python程序生成的Erlang程序,在R14B上试了试。
打开R14B的wxErlang例程sudoku_gui.erl,把函数create_window() 的第一行
Frame = wxFrame:new(wx:null(), -1, "Sudoku", []),
替换成以下内容:
create_window() ->
Bin2 = Unicode:characters_to_binary("中文窗口", uft8),
L2 = Unicode:characters_to_list(Bin2),
utf82u:start(),
U = utf82u:utf82unicode(L2,[]),
Frame = wxFrame:new(wx:null(), -1, U, []),
嗯,程序运行后,正确显示了“中文窗口”,UTF-8确实变成了Unicode。
不过,Erlang自有的GUI工具gs,可以生成UTF-8,但不能显示Unicode,不能使用上面的办法。
总之,Erlang在werl的shell中,可以生成Unicode。在此之外,它只能生成UTF-8。Erlang主要用于开发服务器,尤其是http、web服务器,在网页中UTF-8用量较大。但是,在locale本地程序平台上,Unicode的用途重要,目前Erlang把UTF-8转Unicode这个活计留给了用户。
另外,总结一下在学习Erlang,琢磨Unicode过程中的2个意外收获。
1、发现Erlang字典函数的瑕疵
Erlang的一大特点,是程序内存的“私有化”严格安全管理。没有全局变量、全局内存缓冲。
但我发现,在Erlang R13B之前,字典函数get/1和put/2管理的内存,超出本程序限制,在Erlang shell级全局可用。
虽然当时我并没想到这是一个bug,也没向Erlang官方反映。但在博客文章《Erlang 中文简体字 GB2312 转 Unicode 的办法(3)》发表后,Erlang方面纠正了这个问题。
2、发现Erlang R13B的UTF-8的瑕疵
Erlang能够处理Unicode,是从版本R13A开始的。不过,经过中间7、8个版本,直到目前的R14B03,Erlang只能在werl.exe开启的shell中,把UTF-8多字节编码,解析成双字节构成的单一Unicode字符。而至少在R13A和R13B中,由erlc.exe编译非ASCII字符时,生成的UTF-8存在很大问题,甚至让人怀疑是假的。
发现这个问题,是对R13B测试的结果。据此,我写了《Erlang 中文简体字 GB2312 转 Unicode 的办法》。这两天,又发现了更为确凿的证据。
打开R13B的wxErlang例程sudoku_gui.erl,把函数create_window() 的第一行
Frame = wxFrame:new(wx:null(), -1, "Sudoku", []),
替换成以下内容:
Bin2 = unicode:characters_to_binary("中文窗口", utf8),
L2 = unicode:characters_to_list(Bin2),
gb2u:start(),
U = gb2u:get_unicode(L2,[]),
Frame = wxFrame:new(wx:null(), -1, U, []),
这里的L2本应是UTF-8,实际上却是GB2312。模块gb2u.erl,正是根据GB2312检索对应Unicode的。
目前的R14B已经彻底纠正了这个问题,编译模块时,即使不显式调用unicode库函数,非ASCII码的数据,也会自动编译成UTF-8。于是,我写的那个gb2u.erl,只能用于R13A和R13B这两个版本,在其他版本没有用武之地,它不能根据UTF-8找出对应的Unicode。
怎么办呢?反复查看琢磨Erlang和Python中UTF-8数据的格式,终于看出了规律,GB2312的汉字转成UTF-8时,绝大多数是3个字节。把gb2u.erl稍做改动,有了下面的程序。
def all_gb2312():
s = '''-module(utf82u).
-export([start/0,utf82unicode/2]).
utf82unicode([],U) ->
lists:reverse(U);
utf82unicode([A|T],U) when A < 128 ->
utf82unicode(T,[A|U]);
utf82unicode([A,B,C|Z],U) ->
H = get({A,B,C}),
utf82unicode(Z,[H|U]).
start() ->\n'''
f = open('utf82u.erl','w')
f.write(s)
for row in range(161,248):
if row > 169 and row < 176:
continue
for col in range(161,255):
ch1 = chr(row)
ch2 = chr(col)
w = ch1+ch2
try:
utf8 = w.encode('utf8')
uc = utf8.decode('utf8')
except:
continue
s='put({%s,%s,%s},%s),\n'%(
ord(utf8[0]),ord(utf8[1]),ord(utf8[2]),ord(uc))
f.write(s)
f.close()
UTF-8与Unicode的转换,有具体的算法。网上也可以找到。我也找了个看了看,感觉要弄明白不算太难,但也得花时间认真琢磨,这事儿让人烦:既然有简单的办法,何必费那个劲呢。
上面Python程序生成的Erlang程序,在R14B上试了试。
打开R14B的wxErlang例程sudoku_gui.erl,把函数create_window() 的第一行
Frame = wxFrame:new(wx:null(), -1, "Sudoku", []),
替换成以下内容:
create_window() ->
Bin2 = Unicode:characters_to_binary("中文窗口", uft8),
L2 = Unicode:characters_to_list(Bin2),
utf82u:start(),
U = utf82u:utf82unicode(L2,[]),
Frame = wxFrame:new(wx:null(), -1, U, []),
嗯,程序运行后,正确显示了“中文窗口”,UTF-8确实变成了Unicode。
不过,Erlang自有的GUI工具gs,可以生成UTF-8,但不能显示Unicode,不能使用上面的办法。
总之,Erlang在werl的shell中,可以生成Unicode。在此之外,它只能生成UTF-8。Erlang主要用于开发服务器,尤其是http、web服务器,在网页中UTF-8用量较大。但是,在locale本地程序平台上,Unicode的用途重要,目前Erlang把UTF-8转Unicode这个活计留给了用户。
另外,总结一下在学习Erlang,琢磨Unicode过程中的2个意外收获。
1、发现Erlang字典函数的瑕疵
Erlang的一大特点,是程序内存的“私有化”严格安全管理。没有全局变量、全局内存缓冲。
但我发现,在Erlang R13B之前,字典函数get/1和put/2管理的内存,超出本程序限制,在Erlang shell级全局可用。
虽然当时我并没想到这是一个bug,也没向Erlang官方反映。但在博客文章《Erlang 中文简体字 GB2312 转 Unicode 的办法(3)》发表后,Erlang方面纠正了这个问题。
2、发现Erlang R13B的UTF-8的瑕疵
本文前面已有详细介绍,不再重复。其后的版本,已做纠正。
注:用Python生成的Erlang模块utf82u.erl,已经上传到“我的资源”。
- 解决了Erlang的UTF-8转Unicode中文显示问题
- 中文编码问题(Unicode UTF-8 GBK ...)
- 中文编码问题(Unicode UTF-8 GBK ...) .
- 中文账号显示问题 【UTF-8 转换成 多字节 Unicode】
- [Erlang]解决R17中文编码的问题
- python解决list unicode转中文显示
- PHP echo utf-8 中文 乱码问题的解决
- 解决adb shell input text 中文输入,unicode转utf-8
- 解决了LWUIT中文不能显示的问题
- 解决了delphi for php的中文显示问题
- Mac电脑使用:解决Mac上“文本编码Unicode(UTF-8)不适用”、文本编码“中文 (GB 18030)不适用“的问题
- Atom中文显示乱码问题 UTF-8
- Erlang 中文简体字 GB2312 转 unicode 的办法(1)
- Erlang 中文简体字 GB2312 转 unicode 的办法(2)
- Erlang 中文简体字 GB2312 转 unicode 的办法(3)
- Erlang 中文简体字 GB2312 转 unicode 的办法(1)
- ZF解决中文UTF-8乱码问题
- 解决HTML5 UTF-8 中文乱码问题
- hdu3474单调队列
- 自增运算符前置与后置区别(i++,++i)
- 第三方流量统计网站盈利方式构想(转)
- Repeater隔行变色,两个方式
- cc-mode编译错误
- 解决了Erlang的UTF-8转Unicode中文显示问题
- display:none 和visibility:hidden的区别
- Openfire源代码调试、编译开发环境
- SQL Server 无法生成 FRunCM 线程
- HDU 3905 Sleeping
- hdu1224
- openfire 的源代码分析 clint-to-server
- 技术发展阶段
- static_cast