我希望将任意二进制数据以BLOB形式存储到SQLite数据库中。
使用以下函数将数据作为
现在我想将一个
我运行了以下测试来检查发生了什么:
使用以下函数将数据作为
value
添加:procedure TSQLiteDatabase.AddParamText(name: string; value: string);
现在我想将一个
WideString
转换为它的UTF8表示形式,以便可以存储到数据库中。调用UTF8Encode
并将结果存储到数据库后,我发现数据库中的数据没有进行UTF8解码。相反,在我的计算机地区设置中,它被编码为AnsiString。我运行了以下测试来检查发生了什么:
type
{$IFDEF Unicode}
TBinary = RawByteString;
{$ELSE}
TBinary = AnsiString;
{$ENDIF}
procedure TForm1.Button1Click(Sender: TObject);
var
original: WideString;
blob: TBinary;
begin
original := 'ä';
blob := UTF8Encode(original);
// Delphi 6: ä (as expected)
// Delphi XE4: ä (unexpected! How did it do an automatic UTF8Decode???)
ShowMessage(blob);
end;
在将字符“ä”转换为UTF8后,内存中的数据是正确的(“ä”),但是,一旦我将TBinary
值传递给一个函数(作为string
或AnsiString
),Delphi XE4会出现“魔法类型转换”,原因我不知道。
我已经找到了一个解决方法来避免这种情况:
function RealUTF8Encode(AInput: WideString): TBinary;
var
tmp: TBinary;
begin
tmp := UTF8Encode(AInput);
SetLength(result, Length(tmp));
CopyMemory(@result[1], @tmp[1], Length(tmp));
end;
procedure TForm1.Button2Click(Sender: TObject);
var
original: WideString;
blob: TBinary;
begin
original := 'ä';
blob := RealUTF8Encode(original);
// Delphi 6: ä (as expected)
// Delphi XE4: ä (as expected)
ShowMessage(blob);
end;
然而,我认为使用 RealUTF8Encode
的解决方法很麻烦,我想知道为什么简单的调用 UTF8Encode
没有生效以及是否有更好的解决方案。
WideCharToMultiByte
(一次用于确定输出大小,一次用于实际转换)比使用内存中的StrRec.codePage
操纵并进行单个UTF8Encode
要快 (而不是调用SetCodePage
,这会导致不必要的UniqueString
)。 我知道这将是一个肮脏的黑客,但我想测试一下是否仍然可以比 WinAPI 更快。 也许我在实验过程中做错了什么。 - Daniel MarschallSetLength
将字符串/数组缩短到实际长度,数据将不会被重新定位。 - Daniel Marschall