3

我正在尝试将一些文本(例如č)存储在 Postgres 数据库中,但是在检索此值时,它在屏幕上显示为?. 我不确定为什么会这样,我的印象是它是 UTF-8 不支持的字符,但在 UTF-8 中,但是,从第一个答案来看,这是一个不正确的假设.

原始问题(可能仍然有效):

我已经阅读了有关 UTF-8 代理对的信息,它可以满足我的要求,并且我已经看到了一些涉及stringinfo object的示例TextElementEnumerators,但我无法制定出实用的概念证明。

有人可以提供一个示例,说明您如何将 UTF-16(可能使用此代理对概念)写入和读取到 postgres 数据库。谢谢你。

更新的问题:为什么č字符会作为问号从数据库中返回?

我们使用 NPGSQL 来访问数据库和 VB.Net。

4

3 回答 3

7

UTF-16 中不存在字符,但 UTF-8 中不存在字符。两者都能够编码所有的 Unicode。换句话说,如果你能让 UTF-8 工作,它应该能够存储任何有效的 Unicode 文本。

编辑:代理对实际上是 UTF-16 而不是 UTF-8 的一个特性。它们允许将不在基本多语言平面 (BMP) 中的字符表示为两个 UTF-16 代码单元。基本上,UTF-16 通常被视为固定宽度编码(每个 Unicode 字符正好两个字节),但这只允许 BMP 被干净地编码。代理对是一种将范围扩展到 BMP 之外的(相当老套的)方式。

我非常怀疑您要表示的字符是否在 BMP 之外,因此我怀疑您需要在其他地方寻找问题。特别是,值得在文本进入数据库之前和获取文本之后转储文本的确切字符值(例如,通过将每个字符转换char为)。int理想情况下,在一个简短但完整的控制台应用程序中执行此操作。

于 2011-12-09T16:32:45.897 回答
1

如何将所有 UTF-16“字符”存储在 Postgres 数据库中?

简短的回答,这是不可能的,因为 PostgreSQL 只支持 UTF-8 字符集。

Java、JavaScript、Windows 等基于 UTF-16 的格式可以包含一半代理对,它们在 UTF-8 或 UTF-32 中没有表示。这些可以很容易地通过子串化 Java、JavaScript、VB.Net 字符串来创建。因为它们不能用UTF-8 或 UTF-32 表示,因此不能存储在像 PostgreSQL 这样只支持 UTF-8 字符集的数据库中。

Windows 路径名称可能包含无法读取为 utf-8 ( https://github.com/rust-lang/rust/issues/12056 ) 的一半代理对。

必须使用支持 UTF-16/CESU-8 字符集的数据库系统,该字符集更适合 Java/Android、JavaScript/NodeJS、.Net/wchar_t/Windows 语言/平台。(SQLServer、Oracle(UTF-8 排序规则)、DB2、Informix、HANA、SQL Anywhere、MaxDB 通常支持这样的字符集。

请注意,随着表情符号在基本多语言平面之外表示为 unicode 代码点,这些差异对于西方用户也将变得更加相关。

在 postgres 上,您可以:a)接受损失,b)将数据存储为二进制数据或 c)将它们转换为编码表示(例如 JSON rfc 将它们编码为两个转义字符,以便能够在 UTF- 8/基于 Ascii 的无损失网络格式(https://www.rfc-editor.org/rfc/rfc4627第 2.5 节)。

例如,表情符号位于基本多语言平面之外,这个问题在西方世界也将变得更加相关。

取决于语言应用服务器(Java、Scala、C#/Windows、JavaScript/NodeJS)与 go 的选择以及对语言支持的投资水平(例如在字素边界使用 ICU 字符串拆分功能(https://www.unicode. org/reports/tr29/#Grapheme_Cluster_Boundaries)而不是简单的截断问题可能不太相关。但是今天大多数企业系统和语言都属于 UTF-16 阵营,软件使用简单的子字符串操作。

于 2018-12-15T01:29:51.043 回答
0

至于存储/检索的问题 č

  1. 检查 Postgre db 运行的字符集是 UTF-8 字符集 ( https://www.postgresql.org/docs/9.1/multibyte.html ) 还是可以表示该字符的字符集。

  2. 检查客户端与数据库的连接是否设置为执行适当的代码页转换(对于 VB.Net,这将是从 UTF-16LE 到 UTF-8 或数据库字符集,这通常是连接字符串(字符集)上的参数)。

  3. 检查输入是 VB.net 字节序列中的实际 UTF-8 / UTF-16,而不是 Windows-1250 字节序列。

  4. 检查这不仅仅是输出工具或控制台的限制(例如,Windows 控制台通常不显示 unicode 字符,而是使用 Windows-12xx 字符集(可以尝试https://superuser.com/questions/269818/change- default-code-page-of-windows-console-to-utf-8),但通常最好在 VB.Net 调试器中检查字节序列。

  5. 检查 CHAR/VARCHAR 列的长度是否足以存储您的表示,即使在 NFKD 分解中表示也是如此。

您指示的字形有几种不同的 unicode 表示形式。

 U+010D LATIN SMALL LETTER C WITH CARON
 U+0063 LATIN SMALL LETTER c followed by U+030C COMBINING CARON

以及其他字符集的不同表示形式(例如 ISO-8859-2/Windows-1250 ( https://en.wikipedia.org/wiki/Windows-1250 ) 或 ISO-8859-13/Windows-1257 中的 0xE8。

所有 unicode 表示都属于基本的多语言平面,因此问题标题中指出并在下面回答的 postgre 的 UTF-16 代理问题可能与您的问题无关。

于 2018-12-15T02:23:36.453 回答