erlang更新到R17已有一段时间了。公司项目打算从旧版的erlang迁移到R17,却不料有不少的困扰,当中一个问题是中文问题。
这个问题非常easy重现:新建一个文件t.erl。保存为utf-8无bom格式
-module(t).
-export([test/0]).
test() ->
["我", <<"我">>].
在旧版的erlang中,以下的代码能正常工作。结果就是:
Eshell V5.9.1 (abort with ^G)
1> c(t).
{ok,t}
2> t:test().
[[230,136,145],<<230,136,145>>]
R17编译后的执行结果为:
Eshell V6.0 (abort with ^G)
1> c(t).
{ok,t}
2> t:test().
[[25105],<<17>>]
找到erlang的
文档,erlang更新到R17后,默认编码从Latin-1换成了utf8
In Erlang/OTP 17.0, the encoding default for Erlang source files was switched to UTF-8 and in Erlang/OTP 18.0 Erlang will support atoms in the full Unicode range, meaning full Unicode function and module names
想让R17正确识别utf-8无bom格式的代码文件。方法就是在文件头部加上“%% coding: latin-1”,代码就变成这样:
%% coding: latin-1
-module(t).
-export([test/0]).
test() ->
["我", <<"我">>].
问题是,写个脚本对旧的代码文件做改动尽管不麻烦。但新加进来的文件还要加上这个头部申明,确定有点坑爹。并且受影响的还有 file:consult/1 ,也是要加上头部申明
最脑裂的是erlang没有提供启动參数,用来支持原来的latin-1模式。
所以。这里在erlang基础上又一次实现erlang的编译,代码例如以下:
-module(test).
-compile(export_all).
compile(FileName) ->
compile(FileName, [verbose,report_errors,report_warnings]).
compile(FileName, Options) ->
Module = filename:basename(FileName),
{ok, Forms } = epp:parse_file(FileName, [{default_encoding, latin1}]) ,
{ok, Mod, Code} = compile:forms(Forms, Options),
{ok, Cwd} = file:get_cwd(),
code:load_binary(Mod, FileName, Code),
file:write_file(lists:concat([Cwd, Module, ".beam"]), Code, [write, binary]).
注意了,以上代码不要在R17之前erlang使用,某些接口erlang还没提供支持。执行结果例如以下:
14> c(test).
{ok,test}
15> test:compile("t.erl").
ok
16> t:test().
[[230,136,145],<<230,136,145>>]
另外。也又一次实现了file:consult/1,例如以下:
consult(File) ->
case file:open(File, [read]) of
{ok, Fd} ->
R = consult_stream(Fd),
_ = file:close(Fd),
R;
Error ->
Error
end.
consult_stream(Fd) ->
_ = epp:set_encoding(Fd, latin1),
consult_stream(Fd, 1, []).
consult_stream(Fd, Line, Acc) ->
case io:read(Fd, '', Line) of
{ok,Term,EndLine} ->
consult_stream(Fd, EndLine, [Term|Acc]);
{error,Error,_Line} ->
{error,Error};
{eof,_Line} ->
{ok,lists:reverse(Acc)}
end.
尽管这里能解决erlang R17无法识别中文问题, 但还是希望erlang在以后的版本号能提供一个參数用以兼容latin的代码。
參考:http://blog.csdn.net/mycwq/article/details/40718281