• Erlang的Unicode支持


    在R13A中, Erlang加入了对Unicode的支持。本文涉及到的数据类型包括:list, binary, 涉及到的模块包括stdlib/unicode, stdlib/io, kernel/file。 
    Binary 

    Binary的type属性增加了utf相关的type:utf8, utf16, utf32,其分别对应UTF8, UTF16,UTF32编码。 

    Binary Constructing 

    在Binary构建时, 如果指定了utf相关类型,那么对应的integer的Value必须位于:0..16#D7FF, 16#E000..16#FFFD, 或者 16#10000..16#10FFFF这三个区间中。否则将会提示'bad argument',参数错误。根据指定的的utf类型不同,同一个数据产生的binary不同。 

    对于utf8,每个integer生成1到4个字符;对于utf16,每个integer生成2或4个字符;对于utf32,每个integer生成4个字符。 

    比如, 使用unicode为1024的字符A,  构建一个binary: 

    Erlang代码 
    1. 1> <<1024/utf8>>.      
    2. <<208,128>>  
    3. 2> <<1024/utf16>>.  
    4. <<4,0>>  
    5. 3> <<1024/utf32>>.  
    6. <<0,0,4,0>>  



    Binary Match 

    当进行Binary Match时,如果指定utf相关类型,变量成功匹配后,将拥有一个位于:0..16#D7FF, 16#E000..16#FFFD, 或者 16#10000..16#10FFFF这三个区间中的integer。 

    其更具utf类型的不同,消耗(match)不同数目的bytes。 

    utf8匹配1-4个bytes(参考RFC-2279) 
    utf16匹配2 或 4 个bytes (参考 RFC-2781) 
    utf32匹配4个 bytes 

    比如:继续我们上面的例子 

    Erlang代码 
    1. 4> Bin = <<1024/utf8>>.  
    2. <<208,128>>  
    3. 5> <<U/utf8>> = Bin.  
    4. <<208,128>>  
    5. 6> U.  
    6. 1024  



    这个例子中,U匹配了2个bytes。 

    对于utf相关类型,不能指定unit spec 

    List 

    在list中,每个unicode字符采用integer来表示,因此与latin1的list相比,unicode list中,element的数值可以大于255。 
    下面就是一个有效的unicode list: [1024, 1025] 

    我们可以通过unicode 模块实现 list到binary的转换。 

    unicode module 

    首先请参看下面的type定义: 

    unicode_binary() = binary() with characters encoded in UTF-8 coding standard 
    unicode_char() = integer() representing valid unicode codepoint 
    chardata() = charlist() | unicode_binary() 
    charlist() = [unicode_char() | unicode_binary() | charlist()] 
    a unicode_binary is allowed as the tail of the list 

    external_unicode_binary() = binary() with characters coded in a user specified Unicode encoding other than UTF-8 (UTF-16 or UTF-32) 
    external_chardata() = external_charlist() | external_unicode_binary() 
    external_charlist() = [unicode_char() | external_unicode_binary() | external_charlist()] 
    an external_unicode_binary is allowed as the tail of the list 

    latin1_binary() = binary() with characters coded in iso-latin-1 
    latin1_char() = integer() representing valid latin1 character (0-255) 
    latin1_chardata() = latin1_charlist() | latin1_binary() 
    latin1_charlist() = [latin1_char() | latin1_binary() | latin1_charlist()] 
    a latin1_binary is allowed as the tail of the list 


    我们可以调用unicode:characters_to_list/1 将chardata或latin1_chardata或external_chardata()转化成一个unicode list。 

    如果参数为latin1_chardata,那么Data参数就是一个iodata. 返回的结果list中,每个element为一个integer。默认情况 unicode:characters_to_list/1调用unicode:characters_to_list(Data, unicode) 

    如果我们的CharData为其他类型,我们可以指明InEncoding type。如果此函数执行成功,返回{ok, List}, 如果失败返回{error, list(), RestData}, 其中list为转化成功的部分,RestData为发生错误的位置。 

    我们也可以调用unicode:characters_to_binary/1,将chardata或latin1_chardata或 external_chardata()转化成一个binary。这个函数和unicode:characters_to_list类似,只是结果保存为 binary。 

    如果Data为latin1_chardata, 那么unicode:characters_to_binary/1和 erlang:iolist_to_binary/1功能相同 

    unicode模块中,还有两个于bom相关的函数,可以根据bom指返回对应的encoding类型,也可以根据encoding类型生成对应的bom值。其在保存文件时,经常使用. 

    Examples 

    1, 打开utf8保存的文件 
      文件内容如下test.file: 
    [ 
    {desc, "这是一个测试文件"}, 
    {author, "litaocheng"} 
    ]. 

    其格式为erlang term,保存时选择utf8编码。 
    代码如下: 


    Erlang代码 
    1. %% read content from the file  
    2. test1() ->  
    3.     {ok, [Terms]} = file:consult("test.txt"),  
    4.     Desc = proplists:get_value(desc, Terms),  
    5.     _Author = proplists:get_value(author, Terms),  
    6.       
    7.     % out put the Desc and Author  
    8.     DescUniBin = iolist_to_binary(Desc),  
    9.     DescUniList = unicode:characters_to_list(DescUniBin),  
    10.     io:format("desc bin : ~ts~ndesc bin : ~p~n",[DescUniBin, DescUniBin]),  
    11.     io:format("desc list: ~ts~ndesc list: ~p~n", [DescUniList, DescUniList]).  



    结果: 
    desc bin : 这是一个测试文件 
    desc bin : <<232,191,153,230,152,175,228,184,128,228,184,170,230,181,139,232, 
                 175,149,230,150,135,228,187,182>> 
    desc list: 这是一个测试文件 
    desc list: [36825,26159,19968,20010,27979,35797,25991,20214] 

    首先将内容从list转换为binary, DescUniBin 便是对应的unicode binary。随后通过unicode:characters_to_list/1转化为unicode list最后输出。 
    我们可以看到 unicode list中所有的element为integer, unicode binary中unicode string采用uft8编码。 

    2, 将数据保存成uft8格式 

    Erlang代码 
    1. %% save the binary in utf8 format  
    2. test2() ->  
    3.     [DescList] = io_lib:format("~ts", ["这是一个测试文件"]),  
    4.     DescBin = erlang:iolist_to_binary(DescList),  
    5.     DescList2 = unicode:characters_to_list(DescBin),  
    6.     List = lists:concat(["[{desc,"", DescList2, ""}, {author, "litaocheng"}]."]),  
    7.     Bin = unicode:characters_to_binary(List),  
    8.     io:format("bin is:~ts~n", [Bin]),  
    9.     file:write_file("test_out.txt", Bin).  




    Update: 
    2008.5.4: 
    [DescList] = io_lib:format("~ts", ["这是一个测试文件"]) 
    在erlang shell中DescList为:[36825,26159,19968,20010,27979,35797,25991,20214] 
    在module文件中,DescList为: 
    [232,191,153,230,152,175,228,184,128,228,184,170,230,181,139,232,175, 
              149,230,150,135,228,187,182]

  • 相关阅读:
    机器学习(04)——常用专业术语
    C# 线程同步的三类情景
    线程同步的情景之三
    线程同步的情景之二
    线程同步的情景之一
    Thread.Sleep(0) vs Sleep(1) vs Yeild
    Visual Studio 实用扩展推荐
    为革命保护视力 --- 给 Visual Studio 换颜色
    免费的精品: Productivity Power Tools 动画演示
    如何扩展 Visual Studio 编辑器
  • 原文地址:https://www.cnblogs.com/yanwei-wang/p/4673015.html
Copyright © 2020-2023  润新知