近期在做网址编码相关的工作,发现在用 XE5 编译的时候,一切正常,拿 到 XE7下 就 结果错误了。百度了下,谷歌 了下,有人提出,但是,我没有找到答案,也许都没有碰到这个问题,也许都己经自己默默的解决了,在此 小记一下,方便后人,也方便自己 查寻。
例子 : 原字符 "过年"
httpencode('过年') 结果 :
XE5为 %B9%FD%C4%EA
XE7 调用 相当函数结果 %E8%BF%87%E5%B9%B4
百思不得其解啊,折腾了很长时间,后来终于想到是不是 此函数 官方更新修改了,(没办法,人比较笨)
于是查看源码:
XE5的 web.httpapp 中(分string 和 ansistring, 我用ansistring 版本得到 期望的结果):
1 function HTTPEncode(const AStr: string): string; 2 // The NoConversion set contains characters as specificed in RFC 1738 and 3 // should not be modified unless the standard changes. 4 const 5 NoConversion = [Ord('A')..Ord('Z'), Ord('a')..Ord('z'), Ord('*'), Ord('@'), 6 Ord('.'), Ord('_'), Ord('-'), Ord('0')..Ord('9'), Ord('$'), 7 Ord('!'), Ord(''''), Ord('('), Ord(')')]; 8 var 9 Sp, Rp: PChar; 10 begin 11 SetLength(Result, Length(AStr) * 3); 12 Sp := PChar(AStr); 13 Rp := PChar(Result); 14 while Sp^ <> #0 do 15 begin 16 if Ord(Sp^) in NoConversion then 17 Rp^ := Sp^ 18 else 19 if Sp^ = ' ' then 20 Rp^ := '+' 21 else 22 begin 23 FormatBuf(Rp, 3, string('%%%.2x'), 6, [Ord(Sp^)]); 24 Inc(Rp,2); 25 end; 26 Inc(Rp); 27 Inc(Sp); 28 end; 29 SetLength(Result, Rp - PChar(Result)); 30 end; 31 32 function HTTPDecode(const AStr: string): string; 33 var 34 Sp, Rp, Cp: PChar; 35 S: string; 36 begin 37 SetLength(Result, Length(AStr)); 38 Sp := PChar(AStr); 39 Rp := PChar(Result); 40 Cp := Sp; 41 try 42 while Sp^ <> #0 do 43 begin 44 case Sp^ of 45 '+': Rp^ := ' '; 46 '%': begin 47 // Look for an escaped % (%%) or %<hex> encoded character 48 Inc(Sp); 49 if Sp^ = '%' then 50 Rp^ := '%' 51 else 52 begin 53 Cp := Sp; 54 Inc(Sp); 55 if (Cp^ <> #0) and (Sp^ <> #0) then 56 begin 57 S := Char('$') + Cp^ + Sp^; 58 Rp^ := Char(StrToInt(string(S))); 59 end 60 else 61 raise EWebBrokerException.CreateFmt(sErrorDecodingURLText, [Cp - PChar(AStr)]); 62 end; 63 end; 64 else 65 Rp^ := Sp^; 66 end; 67 Inc(Rp); 68 Inc(Sp); 69 end; 70 except 71 on E:EConvertError do 72 raise EConvertError.CreateFmt(sInvalidURLEncodedChar, 73 [Char('%') + Cp^ + Sp^, Cp - PChar(AStr)]) 74 end; 75 SetLength(Result, Rp - PChar(Result)); 76 end; 77 78 function HTTPEncode(const AStr: AnsiString): AnsiString; 79 // The NoConversion set contains characters as specificed in RFC 1738 and 80 // should not be modified unless the standard changes. 81 const 82 NoConversion = ['A'..'Z','a'..'z','*','@','.','_','-', 83 '0'..'9','$','!','''','(',')']; 84 var 85 Sp, Rp: PAnsiChar; 86 begin 87 SetLength(Result, Length(AStr) * 3); 88 Sp := PAnsiChar(AStr); 89 Rp := PAnsiChar(Result); 90 while Sp^ <> #0 do 91 begin 92 if Sp^ in NoConversion then 93 Rp^ := Sp^ 94 else 95 if Sp^ = ' ' then 96 Rp^ := '+' 97 else 98 begin 99 System.AnsiStrings.FormatBuf(Rp^, 3, AnsiString('%%%.2x'), 6, [Ord(Sp^)]); 100 Inc(Rp,2); 101 end; 102 Inc(Rp); 103 Inc(Sp); 104 end; 105 SetLength(Result, Rp - PAnsiChar(Result)); 106 end;