我有一个使用1.5.5 Firebird嵌入式引擎的应用程序(用Delphi编写)。我正在使用此引擎,因为该应用程序适用于当前部署的Firebird数据库,而较新的嵌入式引擎无法正确打开数据库文件(ODS 10.1)。数据库中的所有字符串都定义为VARCHAR(N),其中N变化。该应用程序曾经是ANSI应用程序,因此数据包含ISO-latin-1字符。现在,应用程序已升级为unicode应用程序。为了在现有数据库(大约10k个实例)中存储Unicode字符,我编写了一个UTF8-BOM(如果你可以调用它),然后字符串的其余部分被认为是UTF8并由数据库层解码。这样我们就可以使用所有现有的数据库,仍然使用所有Unicode字符。
这适用于西欧的所有机器。但是当应用程序在罗马尼亚(具有罗马尼亚语言设置的Windows PC)中运行时:数据库引擎会改变字符。例如:UTF8字符串以字符八位字节EF(ï)开头。数据库引擎将其返回为八位字节69(i)。
如何解决现有数据库的问题?
注意:我在打开数据库时尝试指定字符集OCTETS(使用UIB库),但由于字符集未知,因此失败。
发现问题出在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;
现在我需要检查这个行为是否对库是正确的,并给维护者一个补丁。