Delphi 中的UTF8与Interbase BLOB字段之间的转换

7d7tgy0s  于 2023-03-18  发布在  其他
关注(0)|答案(1)|浏览(107)

摘要:我正在尝试使用TDBMemo中的UTF8文本来存储、检索和显示来自/去往Interbase表中BLOB子类型0字段的希腊字母。希腊字母在DBMemo中显示正确,但当发送到数据库时,它们是乱码的,并且在检索时显示乱码。
Delphi 10.4,Interbase 2020, windows 10操作系统
我使用FireDAC将TDBMemo连接到Interbase表中的BLOB字段:
TFD连接--〉TFD查询--〉TDB数据源--〉TDB备注
这是一个简单的测试程序,没有事件处理程序附加到链中的任何组件。数据库表字段是BLOB子类型0(即二进制)。如果没有UTF8,则字段中的数据将正确显示为DBMemo中的文本(希腊语、西里尔语等-非拉丁语)字符,并正确更新和检索文本,并且可以正确地处理任何带有非ASCII字符的拉丁字母表,例如法语,但在提交更改后,DBMemo和表字段中的所有非拉丁UTF8字符都是乱码。如果我将希腊字母粘贴到DBMemo中,它们会正确显示(因此DBMemo正确地处理UTF8),但是在向表发送之后出现了乱码。表字段是一个二进制BLOB,它应该存储发布到它的任何内容而不更改数据。这意味着从DBMemo到FDQuery的链沿着的某个地方没有将文本保存为UTF8。文本正在被转换为ANSI字符串。
我试过了(使用ANSI to UTF8函数)将DBMemo.Text直接填充到表字段中-不起作用。我尝试过将数据从DBMemo.Text流到BLOB字段中(TStringStream --〉TBLOBStream)-不起作用。我已尝试使用BLOB子类型1(文本)字段使用显式字符集UTF8而不是二进制BLOB -结果相同。在发布之前立即在 Delphi 调试器中检查数据,显示DBMemo。文本正确。使用isql显示文本BLOB UTF8字段表明它在表中已被篡改。
表中的BLOB文本字段可能有问题:如果我尝试使用以下命令直接在IBConsole isql中更新该字段

update biblio set greekfield = ἡλιοδρόμος' where id=10793

update biblio set greekfield = cast('ἡλιοδρόμος' as varchar(2000) character set UTF8) where id=107937

它失败了,显示“不能在字符集之间音译字符”。但也许这只是IBConsole的愚蠢。
由于 Delphi 10完全符合Unicode标准--Interbase 2020也是如此--我希望Delphi能够处理希腊语UTF8字符,至少在Interbase中使用显式UTF文本BLOB表字段时是这样。显然我做错了什么,但在尝试了我能想到的所有方法几个小时后,我仍然无法让它工作。
救命!
大卫

emeijp43

emeijp431#

大卫
是否已在FDConnection中将CharacterSet属性设置为UTF8?https://docwiki.embarcadero.com/RADStudio/Sydney/en/Connect_to_InterBase_(FireDAC)
如果执行上述操作并将 greekfield 列定义为
BLOB子类型1字符集UTF8
它应该能做你想做的事。
例如,下面是一个在InterBase中使用命令行 isql 工具的示例。如果运行该示例时不使用“-names utf8”,则会出现“transliteration error”。但是,如果使用“-names utf8”字符集名称运行该示例,则字符集在连接时设置,从而可以正确地将文本输入/输出从客户端应用程序转换到数据库。

connect 'blob_utf8.ib';
drop database;

create database 'blob_utf8.ib';

create table t1 (greekfield blob sub_type 1 character set UTF8);
commit;

set echo on;
show table t1;

/* Add some Greek data */
insert into t1 values ('ἡλιοδρόμος');
commit;

/* retrieve all and display */
select * from t1;

/* retrieve with greek text cast to UTF8 in the filter condition */
select * from t1 
 where cast (greekfield as varchar(200) character set UTF8) IN ('ἡλιοδρόμος');

quit;

相关问题