TIdMBCSEncoding.Create('ASCII')在Linux上返回MaxCharSize = 0

时间:2012-07-26 10:03:22

标签: linux delphi indy freepascal iconv

我的环境是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用户也看到了这个问题)

1 个答案:

答案 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