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
,当超过255 时 http_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].
本文由 qingchuwudi 原创、整理,除非另有声明,本作品采用知识共享署名 3.0 *许可协议进行许可。