为啥 Delphi IBX TWideMemoField 转换 UTF8 字符串中的字节顺序以及如何避免它?
Posted
技术标签:
【中文标题】为啥 Delphi IBX TWideMemoField 转换 UTF8 字符串中的字节顺序以及如何避免它?【英文标题】:Why Delphi IBX TWideMemoField converts byte order in UTF8 string and how to avoid it?为什么 Delphi IBX TWideMemoField 转换 UTF8 字符串中的字节顺序以及如何避免它? 【发布时间】:2018-09-03 06:39:19 【问题描述】:我在Firebird 3数据库上使用带有IBX的Delphi 2009(我没有选择其他技术,我必须适应这种情况)。我有以下定义:
Firebird BLOB 字段定义为:
BLOB SUB_TYPE 0 SEGMENT SIZE 80
TWideMemoField 定义为:
object MainQryNOTES: TWideMemoField
FieldName = 'NOTES'
Origin = 'INVOICES.NOTES'
ProviderFlags = [pfInUpdate]
BlobType = ftWideMemo
end
测试字符串是“Цель по инфляции, %”,可以从 IBExpert 软件的 BLOB 字段中读取为:
26 04 35 04 3B 04 4C 04 20 00 3F 04 3E 04 20 00
38 04 3D 04 44 04 3B 04 4F 04 46 04 38 04 38 04
2C 00 20 00 25 00
奇怪的是 Delphi 颠倒了字节顺序,例如西里尔字符 Ц 的 HEX UTF8 表示为 04 26,但它在数据库中存储为 26 04,其他字符也完全相同(可以借助表 https://www.w3schools.com/charsets/ref_utf_basic_latin.asp 和 https://www.w3schools.com/charsets/ref_utf_cyrillic.asp 进行检查) .在我的例子中,我只有 2 字节的字符,但我想类似的情况也会出现在 3 和 4 字节的 UTF8 字符中。
那么 - 如何配置 TWideMemoField 以要求不转换 UTF8 字符串的字节顺序?
【问题讨论】:
你为什么要(实际上)再次问同样的问题,而不是编辑原件?参考:***.com/q/52138881/2292722 在这个问题中,我试图了解如何以 UTF8 格式配置从 TWideMemoField 到数据库的保存,在那个问题中,我将尝试了解如何在 php 中将 UTF16LE 转换为 UTF8。 试试sql.ru论坛,说不定有人遇到过。此外,也许您可以找到比 d2009 更新的 IBX 开箱即用 你的 BLOB 字段是二进制而不是文本的,所以我想知道 Firebird 是否会尝试转换它。如果有的话,您没有指定 blob 字段字符集/排序规则,也没有指定您设置的连接字符集。关于 BLOB 子类型:firebirdsql.org/file/documentation/reference_manuals/… 【参考方案1】:您的文本未编码为 UTF8,而是编码为 UTF16。字符 Ц 是U+0426。按照惯例,16 位代码单元以小端字节顺序存储,$26 $04。
换句话说,一切都按照预期和设计运行,我认为您没有必要尝试修复任何东西,因为没有任何问题。
【讨论】:
解决这个问题的一个原因是 Firebird 本身不支持 UTF-16,这意味着您需要将其作为二进制数据处理,而不是能够将数据库中的内容作为文本处理(即是:你不能正确使用一些内置的数据库函数和运算符来进行字符串操作)。 @MarkRotteveel 所以你说的问题是使用了UTF-16,而不是字节顺序?前进的方向是确保使用 UTF-8? 只有 OP 可以确定这一点,但我会说是的,UTF-16 被持久保存到数据库的事实是一个潜在的问题,OP 可能想要解决这个问题并且确保改为存储 UTF-8。 @MarkRotteveel 这将要求他即时更改字段类型,如果依赖项可能很难以上是关于为啥 Delphi IBX TWideMemoField 转换 UTF8 字符串中的字节顺序以及如何避免它?的主要内容,如果未能解决你的问题,请参考以下文章
为啥 Delphi 程序员会使用 Lazarus 作为 IDE 而不是使用 Delphi 的 IDE? [关闭]