2

我有一个使用 1.5.5 Firebird 嵌入式引擎的应用程序(用 Delphi 编写)。我正在使用这个引擎,因为该应用程序适用于当前部署的 Firebird 数据库,并且较新的嵌入式引擎无法正确打开数据库文件(ODS 10.1)。数据库中的所有字符串都定义为 VARCHAR(N),其中 N 不同。该应用程序曾经是一个 ANSI 应用程序,因此数据包含 ISO-latin-1 字符。现在应用程序已升级为 unicode 应用程序。为了将 Unicode 字符存储在现有数据库中(大约 10k 个实例),我编写了一个 UTF8-BOM(如果你可以这样称呼它),然后字符串的其余部分被认为是 UTF8 并由数据库层解码。这样我们就可以使用所有现有的数据库,并且仍然使用所有 Unicode 字符。

这适用于西欧的所有机器。但是当应用程序在罗马尼亚(具有罗马尼亚语设置的 Windows PC)中运行时:数据库引擎会更改字符。例如:UTF8 字符串以字符 octet EF (ï) 开头。数据库引擎将其返回为八位字节 69 (i)。

现有数据库如何解决这个问题?

注意:我在打开数据库(使用 UIB 库)时尝试指定字符集 OCTETS,但由于字符集未知,因此失败。

发现问题出在 UIB(本例中使用的数据库层)。UIB 处理 csNONE 的方式是,如果你给它一个字节字符串(数据类型 AnsiString),它会通过简单地将字节扩展为单词并使用当前线程代码页进一步减少它来转换为 UnicodeString。由于罗马尼亚没有使用 iso-latin-1 作为它的代码页......数据在那里被破坏了。

现在我在 UIBLib 中更改了以下例程(例如,当给出 ansistring 并且 charset 为 none 并且请求 ansistring 参数时 -> 根本不进行转换):

  procedure TSQLDA.EncodeStringA(Code: Smallint; Index: Word; const str: AnsiString);
  begin
  {$IFDEF UNICODE}
    if FCharacterSet = csNONE then begin // new
      EncodeStringB( Code, Index, str ); // new
    end else begin                       // new
      EncodeStringB(Code, Index, MBUEncode(UniCodeString(str), CharacterSetCP[FCharacterSet]));
    end;                                 // new
  {$ELSE}
    EncodeStringB(Code, Index, str);
  {$ENDIF}
  end;

现在我需要检查这个行为对于库是否正确,并给维护者一个补丁。

4

0 回答 0