我的环境是i386上的Ubuntu 12.04 Linux。我可以看到只安装了UTF-8语言环境(在/var/lib/locales/supported.d/local
中):
de_DE.UTF-8 UTF-8
en_US.UTF-8 UTF-8
~
现在出现问题:
TIdIOHandler.InitComponent调用TIdTextEncoding.Default,后者又调用 TIdMBCSEncoding.Create('ASCII')。
那就是行
FMaxCharSize := GetByteCount(PWideChar(@cValue[0]), 2);
执行,并且GetByteCount返回零 - 这不应该发生(期望值为1,因为ASCII是单字节编码)。
返回零值的地方是IdGlobal中的第2288行:
if iconv(FFromUTF16, @LCharsPtr, @LCharCount, @LBytesPtr, {$IFNDEF KYLIX}@{$ENDIF}LByteCount) = size_t(-1) then
begin
Result := 0;
Exit;
end;
这可能是由缺少UTF-16语言环境引起的吗? (我在第一次尝试时没有成功安装UTF-16支持,也许Linux上的其他Indy用户也看到了这个问题)
答案 0 :(得分:2)
Indy目前没有对iconv()
错误进行充分处理,因为iconv()
依赖于平台特定的errno
变量,这些变量很难在Indy中跨多个平台实现(这不是如果已实现iconv()
以直接返回其自己的错误代码,则会出现问题。并非所有iconv()
错误都是真正的失败,但是Indy还不知道,所以它将所有错误视为失败(为什么GetByteCount()
失败时返回0而不是引发异常,这是因为{ {1}}以Embarcadero的TIdTextEncoding
类为模型,因此必须与API兼容。这将在Indy 11中发生变化。)
ICONV应该本地实现其字符集,因此操作系统中安装的位置无关紧要。在这种情况下,我怀疑SysUtils.TEncoding
无法将代码点iconv()
从UTF-16转换为$10FFFD
中的ASCII,因为它超出了ASCII范围,这是其中一种情况Indy需要查看TIdMBCSEncoding.Create()
以区分失败和部分转换,但目前还没有这样做。
作为一种变通方法,您可以编辑IdGlobal.pas以使errno
属性getter使用TIdTextEncoding.Default
类而不是TIdASCIIEncoding
类,因为Indy有自己的ASCII实现,即不依赖于ICONV。
TIdMBCSEncoding