• Erlang编码utf8转urlunicode(二)


    Erlang里面utf8 == urlunicode,差别只是:tf8是10进制,转成16进制就是url

    下面是把utf8转成url格式的方法:

    %% utf8 -> urlunicode
    utf8_to_url(Data) when is_binary(Data)->
        Data2 = [T || <<T:8>> <= Data],
        utf8_to_url(Data2, []);
    utf8_to_url(Data) when is_list(Data)->
        utf8_to_url(Data, []).
    
    utf8_to_url([], Url) -> Url;
    utf8_to_url([Utf8Code | Tail], Url) ->
        NewUrl = Url ++ "%" ++ integer_to_list(Utf8Code, 16),
        utf8_to_url(Tail, NewUrl).
    

    例子:

    1> A = <<"汉字"/utf8>>.
    <<230,177,137,229,173,151>>
    2> util:utf8_to_url(A).
    "%E6%B1%89%E5%AD%97"
    

    注意:不管是二进制还是列表,里面的整数都要是utf8的,即范围 0~255

    3> "汉字".
    [27721,23383]
    

    这种不可以直接转,需要先转成utf8。

    7> A = "汉字".
    [27721,23383]
    8> unicode:characters_to_binary(A).
    <<230,177,137,229,173,151>>
    9> B = unicode:characters_to_binary(A).
    <<230,177,137,229,173,151>>
    10> util:utf8_to_url(B).
    "%E6%B1%89%E5%AD%97"
    

    中间经过了一步转换。
    简单点的做法就是全部用二进制

    <<String/utf8>>
    

    PS

    上面的方法只是为了理解编码,实际项目中不需要通过上面的方法完成。
    Erlang里面url编码使用http_uri:encode/1
    比如对

    http://alidns.aliyuncs.com/?Format=XML&AccessKeyId=testid&Action=DescribeDomainRecords&SignatureMethod=HMAC-SHA1&DomainName=example.com&SignatureNonce=f59ed6a9-83fc-473b-9cc6-99c95df3856e&SignatureVersion=1.0&Version=2015-01-09&Timestamp=2016-03-24T16:41:54Z

    ?后面的部分进行编码:

    1> Url1 = "Format=XML&AccessKeyId=testid&Action=DescribeDomainRecords&SignatureMethod=HMAC-SHA1&DomainName=example.com&SignatureNonce=f59ed6a9-83fc-473b-9cc6-99c95df3856e&SignatureVersion=1.0&Version=2015-01-09&Timestamp=2016-03-24T16:41:54Z".
    ... ...
    2> http_uri:encode(Url1).
    "Format%3DXML%26AccessKeyId%3Dtestid%26Action%3DDescribeDomainRecords%26SignatureMethod%3DHMAC-SHA1%26DomainName%3Dexample.com%26SignatureNonce%3Df59ed6a9-83fc-473b-9cc6-99c95df3856e%26SignatureVersion%3D1.0%26Version%3D2015-01-09%26Timestamp%3D2016-03-24T16%3A41%3A54Z"

    再PS:汉字等编码


    以上是 0~255,当超过255http_uri:encode/1就没办法处理。
    官方有个edoc_lib.erl模块,里面的函数超过 255 可以处理,但结果是错误的。

    例如:

    标签 测试 进行编码

    Eshell V8.3  (abort with ^G)
    1> edoc_lib:escape_uri("标签 测试").
    "%c0%87%c1%be%20%c1%8b%c3%95"

    但其真实结果是:%E6%A0%87%E7%AD%BE%20%E6%B5%8B%E8%AF%95

    • 解决方案:

      -module(uri).
      
      -export([encode/1]).
      
      encode(S) when is_list(S) ->
          encode(unicode:characters_to_binary(S));
      encode(<<C, Cs/binary>>) when C >= $a, C =< $z ->
          [C] ++ encode(Cs);
      encode(<<C, Cs/binary>>) when C >= $A, C =< $Z ->
          [C] ++ encode(Cs);
      encode(<<C, Cs/binary>>) when C >= $0, C =< $9 ->
          [C] ++ encode(Cs);
      encode(<<C, Cs/binary>>) when C == $. ->
          [C] ++ encode(Cs);
      encode(<<C, Cs/binary>>) when C == $- ->
          [C] ++ encode(Cs);
      encode(<<C, Cs/binary>>) when C == $_ ->
          [C] ++ encode(Cs);
      encode(<<C, Cs/binary>>) ->
          escape_byte(C) ++ encode(Cs);
      encode(<<>>) ->
          "".
      
      escape_byte(C) ->
          "%" ++ hex_octet(C).
      
      hex_octet(N) when N =< 9 ->
          [$0 + N];
      hex_octet(N) when N > 15 ->
          hex_octet(N bsr 4) ++ hex_octet(N band 15);
      hex_octet(N) ->
          [N - 10 + $A].

      参考:
      URL encode in Erlang
      github.com/renatoalbano/3796470

    知识共享许可协议 本文由 qingchuwudi 原创、整理,除非另有声明,本作品采用知识共享署名 3.0 中国大陆许可协议进行许可。

  • 相关阅读:
    TCP详解——传输控制协议(总述)
    sublime text3使用插件SublimeTextTrans设置透明度
    vue学习1
    js事件绑定/监听
    如何成为顶级程序猿
    HTML5中meta属性
    windows安装SVN服务器并设置开机启动
    oracle安装登录sqlplus / as sysdba然后报错ERROR: ORA-01031 insufficient privileges
    移动端和PC端有什么区别
    div+css通用兼容性代码整理
  • 原文地址:https://www.cnblogs.com/qingchuwudi/p/12077737.html
Copyright © 2020-2023  润新知