使用Free Pascal 3.0.4,这个测试程序正确地写了ÄÖÜ
program FPCTest;
uses IdURI;
begin
WriteLn(TIdURI.URLDecode('%C3%84%C3%96%C3%9C'));
ReadLn;
end.
但是,如果使用单位LazUTF8(如here所述),它会写入???
program FPCTest;
uses IdURI, LazUTF8;
begin
WriteLn(TIdURI.URLDecode('%C3%84%C3%96%C3%9C'));
ReadLn;
end.
如何为使用LazUTF8的程序修复此解码错误?
当String
类型是AnsiString
1的别名时,Indy的大部分功能都会暴露额外的参数/属性,以便用户控制在执行AnsiString
转换的操作中传递AnsiString<->byte
值时使用的ANSI编码。
1:2009年之前的德尔福,以及不使用{$ModeSwitch UnicodeStrings}
和{$Mode DelphiUnicode}
的FreePascal / Lazarus(FYI,Indy 11将使用它们!)。
在大多数情况下,Indy的默认字节编码是ASCII(因为Indy实现的许多Internet协议最初只支持ASCII - 个别Indy组件根据协议将其自身升级为UTF),尽管有些东西使用操作系统默认代码页/字符集代替。
通过在GIdDefaultTextEncoding
单元中设置全局IdGlobal
变量,可以在运行时更改Indy的默认字节编码,例如:
GIdDefaultTextEncoding := encUTF8;
但是,在这种特殊情况下,TIdURI.URLEncode()
不使用GIdDefaultTextEncoding
,但它确实有一个可选的ADestEncoding
参数,可用于为返回的AnsiString
指定特定的字节编码(除了可选的AByteEncoding
参数以指定字节编码)解析url八位字节 - 默认为UTF-8),例如:
TIdURI.URLDecode('%C3%84%C3%96%C3%9C'
{$IFNDEF FPC_UNICODESTRINGS}, IndyTextEncoding_UTF8, IndyTextEncoding_UTF8{$ENDIF}
)
上面将解析url编码的八位字节为UTF-8,然后按原样在UTF-8编码的AnsiString
中返回该数据。
如果没有为ADestEncoding
指定输出编码,则URLDecode()
默认为操作系统默认值。如果您希望它使用GIdDefaultTextEncoding
,请在IndyTextEncoding_Default
参数中指定ADestEncoding
:
TIdURI.URLDecode('%C3%84%C3%96%C3%9C'
{$IFNDEF FPC_UNICODESTRINGS}, IndyTextEncoding_UTF8, IndyTextEncoding_Default{$ENDIF}
)
另一个选择是使用IndyTextEncoding(CodePage)
函数为ADestEncoding
,传递它FreePascal的DefaultSystemCodePage
变量,LazUtils
包设置为CP_UTF8
2:
TIdURI.URLDecode('%C3%84%C3%96%C3%9C'
{$IFNDEF FPC_UNICODESTRINGS}, IndyTextEncoding_UTF8, IndyTextEncoding(DefaultSystemCodePage){$ENDIF}
)
2:我在Indy的问题跟踪器中有opened a ticket,以便在编译FreePascal / Lazarus时添加对DefaultSystemCodePage
的支持。
通过TIdURI.URLDecode行中的这一变化,可以使用386ff LazUTF8:
{$IFDEF FPC}
Result := string(AByteEncoding.GetString(LBytes));
{$ELSE}
{$IFDEF STRING_IS_ANSI}
EnsureEncoding(ADestEncoding, encOSDefault);
CheckByteEncoding(LBytes, AByteEncoding, ADestEncoding);
SetString(Result, PAnsiChar(LBytes), Length(LBytes));
{$ELSE}
Result := AByteEncoding.GetString(LBytes);
{$ENDIF}
{$ENDIF}
笔记
此更改假定始终使用LazUTF8单元,并且每次使用新版本时都需要应用Indy源代码更改。
此外,我发现无法使用和不使用LazUTF8的方式修复TIdURI.URLDecode。