议决运用顺序存储和检索 XML
XML 编码
字符编码
在汗青上,术语 字符集、字符编码 和 码页 都有雷同的意义:一个字符集和一个二进制码集,其中每个码示意一个字符。(码页是来自 IBM 的一个术语,示意一个大型主机或 IBM PC 上的一个字符集。) 官方字符集称号由 Internet Assigned Numbers Authority (IANA) 维护。欲观念更多信息,请参阅 参考质料 小节。
遗留字符编码
东方一些罕有的遗留字符集有 US-ASCII、EBCDIC、码页 437、码页 1252、8859-1、1208 和 Latin-1。这些都是将一个字符编码为一个字节。
-
码页 437: 在美国的 Microsoft Windows 上,默许码页是 437;IANA 官方编码称号为 ibm-437。 它有一些非英语字符(例如 "ae" 连字、带重音的小写元音、一些希腊字母、法语引号 "<<" 和 ">>" 以及 48 个图形字符(DOS 和基于字符的顺序的遗产)。
-
码页 1252: 在 DB2 的起头菜单组中,在 Command Line Tools 下有两个菜单项: Command Line Processor 和 Command Window。它们都是首先运转一个顺序 db2clpcp.exe,该顺序将码页从默许的 437 改为(美国的)1252。 码页 1252(Microsoft 也称 "Latin-I")中有 "ae" 连字,大写和小写的重音字符以及欧元标记(十六进制码为 0x80),然则没有希腊字母。
-
码页 1208: 当执行
CREATE DATABASE USING CODESET UTF-8
时,呼应的数据库码页为 1208:db2 get db cfg for sample | grep "code"Database code page = 1208Database code set = UTF-8Database country/region code = 1
-
字符集 iso-8859-1: 该字符集也称 Latin-1,在英国或西欧的 Web 页面上比拟罕有。它有 "ae" 连字、大写和小写的重音拉丁字母,然则没有希腊字母,也没有欧元标记。
参考质料中可以找到这些字符集和另外字符集的定义的链接。
回页首
Unicode
任何遗留编码都是有限定的,因为它只能示意多数言语中的文本。经管多种编码是件头痛的事情,这不仅仅是因为大大都运用顺序和数据库只能处理一种编码,另有许多另外缘由。Unicode 便是为了处理这个成果而缔造的。它是用于默匡正在运用的齐备言语中的齐备字符的字符集,而且留有增进空间。
在 Unicode 中,一个字符集的庞大思想被英华为 4 个观念:
- 字符集 便是可以被编码的齐备字符的集合。它没有指定编码。
- 编码字符集是专一整数的集合,用于示意字符汇集的一些或全数字符,一个数字(或 码点)对应一个字符。也称 character set、charset 或 code set。它与码页是同义词。Unicode 码点局限为 0 到 0x10FFFF(大约 110 万)。
-
新近,Unicode 定义了不到 64,000 字符的字符集,所以可以用 16 位(2 字节)码点指定一个编码字符集。跟着更多字母表的参与,字符集超越了 64,000 个字符。 另一个成果是,许多处理 US-ASCII 的计较机系统(尤其是用 C 编写的顺序)或另外计较机系统运用一个 null 或零字节(在 C 中为
\0
)标记一个字符串的扫尾。然则将 Unicode 码点间接编码为 16-位或更大的数字时,会包括一些 null 字节,它们会分袂这些顺序。所以 Unicode 引入了一个新的观念,即字符编码表(CEF), ,它每每被简称为字符编码(character encoding)或编码(encoding)。CEF 是从编码字符汇集的码点到一组分歧的整数(或 code unit)之间的映射,这些字符理论上被编码为其中的整数。编码单元是用于编码字符的最小单元。一个字符可以用一个或多个编码单元示意,从而容许编码更多的字符。
所以码点 只是用于引用的,因此可以说 “那个 字符”。Java
String
、Cchar[]
或文件中的理论字节大体分歧,这取决于字符编码表。有些 Unicode 字符编码表是 UTF-8、UTF-16 和 UTF-32。数字 8、16 和 32 示意编码单元中的位数。- DB2 运用 UTF-8 为每个字符运用 1 到 4 个编码单元(即字节)。在规定 UTF-8 数据库中的 [VAR]CHAR 列的长度时,这一点很次要:一个字符大体占 1 到 4 个字节。UTF-8 字符编码表不包括任何 null 字节,这种字节对于 C 比拟等闲。
- 在 Java 言语运用的 UTF-16 字符编码表中,最常用的码点低于 64K,UTF-16 字符码等于码点。更高的码点需求两个编码单元。
- UTF-32 是专一定长的 UTF,它议决添加空间成本简化一些处理。编码单元老是等于码点。
因为 Unicode 尺度限定遗留码点,使齐备 UTF 编码都能示意任何码点,因此 UTF 之间的译码不会组成字符损掉。
Unicode 码点在文档中平日被写为
U hhhh
,其中hhhh
示意 4 个十六进制数字,用于 2 字节的码点;对于 64K 以上的码点,因为需求 4 个字节,因此两次运用该语法。 详尽,该语法是在文档中运用的,XML 和编程言语中专门有效于指定 Unicode 笔墨的语法;欲观念更多信息,请参阅上面的 "编码中的字符" 小节。 -
字符编码体例(character encoding scheme)指定在示意字符的字节流中的一个编码单元中如何胪列字节。UTF-16 和 UTF-32 供应了指定字节按次的体例,即 big-endian(默许)或 little-endian。对于 UTF-8,一个编码单元便是 1 字节,所以不存在按次 -- 换句话说,无论计较机的 endian 按次是什么,编码单元的按次老是一样的。
回页首
哪种编码?
不管用什么来处理字符数据,都必需知道字符集、字符编码表和数据的字符编码体例。
外部编码
在 XML 之外,文本只需外部编码。外部编码由码页定义,大概由情况中的职位地方、运用顺序、变量范例、函数或体例(例如 Java 体例 String.getBytes(String encoding)
)中指定的编码来定义。
为了确天命据库创建时所基于的数据库码页,可以运转:
db2 get db cfg for database-name
,并查察 "Database code page" 参数的值。
在 Windows 上,编码的有些方面取决于安顿的操纵系统的版本。议决 Control Panel applet "Regional and Language Options" 可以改动地区和键盘的某些方面。可以掀开一个下令窗口,输入下令 CHCP
,来看看码页是什么。
在 Linux 和 UNIX 上,运动情况是议决地区设置来确定的,地区设置包括关于言语、地区和编码集的信息。为了确定运动码页,运转:
locale
外部编码
XML 数据还可以有外部编码。外部编码位于 XML 文档的外部。外部编码有两种:
- 编码属性
- Byte Order Mark (BOM)
编码属性 在文档顶部的 XML 声明部门,它指定一种官方 IANA 编码称号:
<?xml version="1.0" encoding="UTF-8"?>
BOM 是文件开头部门的一系列新鲜的字节,它标明一种 Unicode 编码。为了读取 XML 声明,XML 理会器需求知道或推想编码。然则它可以正确无误地读取 BOM。
表 1. Unicode 编码的 Byte Order Mark
UTF-8 X'EFBBBF' UTF-8
UTF-16 Big Endian X'FEFF' UTF-16
UTF-16 Little Endian X'FFFE' UTF-16
UTF-32 Big Endian X'0000FEFF' UTF-32
UTF-32 Little Endian X'FFFE0000' UTF-32
分歧等编码
假定 XML 文档的理论编码、外部编码和外部编码(BOM 或 XML 声明)分歧等,那么该文档便是不成读的。一个破例是外部编码为 Unicode(例如运用 UTF-16 的一个 Java String
):任何外部编码都被忽略。当一个不撑持 XML 的进程译码(也便是改动理论编码)大概在不撑持外部编码的情况下变更文档时,就会产生一个罕有的成果。Java 言语、CLI 和嵌入式 SQL 运用顺序中对字符串的某些处理可以在不改动外部编码的情况下举办译码。欲观念如何防范这个成果,请参阅上面的"创议"小节。
回页首
编码中的字符
在 Windows 中,为了在键盘上输入分歧言语的文本,可以在 Windows Control Panel 中 "Regional and Language Options" 下单击 Languages 标签页上的 Details 按钮来改动输入言语和键盘机关。可以添加多种言语和键盘,而且用一个热键在它们之间举办切换。(对不起,这里没有 Unicode "言语" 或键盘 -- 因为它必需异终大才行!)
Windows Notepad 合用顺序可以用 "ANSI"(windows-1252 或雷同)、"Unicode" (UTF-16 little endian,Intel 和 AMD CPU 的 endian 按次)、"Unicode big endian"(默许 UTF-16)和 UTF-8 编码生涯文件。对于 UTF,Notepad 用一个 BOM(没有 XML 声明)事后思索文件。
在 Java String
笔墨(授与 Unicode)中,运用一个本义序列:\udddd
,其中 dddd
示意用于 Unicode 码点的 4 个十六进制数字。
在 XML 和 HTML 中,可觉得码点运用一个 XML 数字引用(或 字符引用):&#n
,其中 n
是用于 Unicode 的一个十进制数字。例如,欧元标记的十进制引用是 €。议决在数字前面加上 x
,也可以将码点指定为一个十六进制数字:&#xn
。例如,欧元标记的十六进制引用是 €。十六进制引用平日更等闲,因为码点平日是用十六进制指定的。对于数字引用,前面的 0 被忽略。每个字符都必需零丁转移或引用:例如,"!"" 是 "!"" (叹息号,双引号),而 "™" 是 "?"(商标)。
表 2 展现了一些示例字符和它们的 Unicode 码点以及 UTF 和两种遗留的东方码页中的字符编码。
回页首
Java 言语中的编码
Java String
(和类和体例名等标识符)是用 UTF-16 编码的;然则源文件是用今后码页而不是 UTF-16 编码的。当用 javac
编译一个 Java 顺序时,编译器将 String
笔墨从源文件的编码转换为 UTF-16。为了指定源文件运用另一种编码,可以运用 javac
选项 -encoding code-set-name
。该选项容许在标识符和笔墨字符串中运用一种分歧的编码。
DB2 9 供应了一个助手类 com.ibm.db2.jcc.DB2Xml
,这个类可以资助在数据库与 Java 运用顺序之间传输和转换数据。它对 XML 知道得更多;例如,有些体例可以依据理论的编码转换串行化 XML 文档的外部编码,使它们贯穿连接一概。
表 3. JDBC getter 体例:前去范例、编码和声明
getDB2String()
String
UTF-16 否getDB2XmlString()
String
ISO-10646-UCS-2 是getDB2Bytes()
byte[ ]
UTF-8 否getDB2XmlBytes(String targetEncoding)
byte[ ]
As specified 是getDB2AsciiStream()
InputStream
ASCII 否getDB2XmlAsciiStream()
InputStream
ASCII 是getDB2CharacterStream()
java.io.Reader
UTF-16 否getDB2XmlCharacterStream()
java.io.Reader
ISO-10646-UCS-2 是getDB2BinaryStream()
InputStream
UTF-8 否getDB2XmlBinaryStream(String targetEncoding)
InputStream
As specified 否DB2 9 附带了 2 种 JDBC 驱动顺序,它们可以用三种分歧的体例衔接到 DB2(DB2 9 不撑持 JDBC Type 3 驱动顺序):
- DB2 Driver for JDBC and SQLJ,一种通用的 JDBC 驱动顺序,可以用以下体例衔接:
- JDBC Type 4 驱动顺序
- JDBC Type 2 驱动顺序
- DB2 JDBC Type 2 Driver(一种遗留驱动顺序)
创议运用通用的 DB2 driver for JDBC and SQLJ。从 DB2, Version 8.2 起头,就分歧意运用遗留 Type 2 驱动顺序。遗留 Type 2 JDBC 驱动顺序不克不及与 DB2 类 com.ibm.db2.jcc.DB2Xml
一路运用,而且在某些 JDBC 体例中以分歧的体例处理 XML。例如,一个 XML 列的 SELECT
(没有显式的 XMLSERIALIZE()
)上的 get
体例(例如 ResultSet.getBinaryStream(column)
、ResultSet.getCharacterStream(column)
、ResultSet.getString(column)
)会添加一个 BOM 和 XML 声明到串行化 XML 中。要么外部编码(UTF-16)与理论编码不婚配,要么 BOM 被损坏,从而招致文档不成用。
关于 JDBC 驱动顺序版本的更多信息,请参阅 表 4。
对于任何范例的 JDBC 衔接,假定要以今后用户之外的另外用户举办衔接,则必需在衔接 URL 或 getConnection()
的 Properties
参数中指定所需的用户名和密码。
DB2 在 IBM\SQLLIB\samples\xml\java\jdbc 中供应了示例 JDBC 运用顺序,例如 XmlInsert.java。假定运用它们举办实验,那么要戒备,在默许情况下,这些运用顺序用遗留的 Type 2 驱动顺序衔接到 DB2。(请查察 Util.java
文件中的助手类 Db
。)为了用 Type 4 驱动顺序举办衔接,必需指定处事器、端口、用户和密码的下令行参数。 假定要看语法旧事,可以用参数 -help
运转这个类:
prog_name -u2 [dbAlias] [userId passwd] (use universal JDBC type 2 driver) prog_name [dbAlias] server portNum userId passwd (use universal JDBC type 4 driver)
例如:
java -cp ".;%>
下载 小节中有演示 DB2、JDBC 和 DB2Xml
类如那处置编码的示例代码。
回页首
CLI 中的编码
当将 XML 拔出 DB2,并运用 SQLBindParameter()
将一个变量绑定到一个 XML 列时,CLI 依据上面表 5 中的输入规则确定 XML 的编码。假定编码由运用顺序码页确定,然则文档另有一个外部编码(一个 BOM 或 XML 声明),则外部编码与外部编码必需一概。当从 DB2 中将 XML 取出到一个主变量中时,数据将依据表 5 运用一种外部编码(含编码属性的一个 XML 声明)来编码。
表 5. CLI 范例
SQL_C_CHAR
运用顺序的码页 与输入不异SQL_C_DBCHAR
运用顺序的码页 与输入不异SQL_C_WCHAR
UCS-2 与输入不异SQL_C_BINARY
读外部编码 UTF-8回页首
嵌入式 SQL 中的编码
当议决一个嵌入式 SQL(ESQL)主变量将 XML 拔出 DB2 中时,XML 的编码依据表 6 中的输入规则来确定。假定编码由运用顺序码页确定,然则文档另有一个外部编码(一个 BOM 或 XML 声明),则外部编码与外部编码必需一概。当从 DB2 中将 XML 取出到一个 ESQL 主变量中时,数据将依据表 6 运用一种外部编码(含编码属性的一个 XML 声明)来编码。
表 6. ESQL 范例
XML AS CLOB
、XML AS CLOB_FILE
运用顺序的码页 与输入不异XML AS DBCLOB
、XML AS DBCLOB_FILE
运用顺序的码页 与输入不异XML AS BLOB
、XML AS BLOB_FILE
读外部编码(注 1) UTF-8char[]
之类的一个庞大范例 运用顺序的混淆码页(注 2) 与输入不异注 1: 假定一个 BLOB 范例的变量没有任何外部编码,则 DB2 假定其编码为 UTF-8。
注 2:为了议决一个庞大范例(例如 char
)变量拔出 XML,可以运用 SQL 函数 XMLCAST(? AS XML)
将其映射到 XML。
回页首
创议
- 将字符串笔墨(例如提示和错误旧事)从源代码直达移到某种属性或初始化文件中,大概转移到一个数据库表中。这样做便于将运用顺序翻译成另外言语。然则,需求在运用顺序中硬编码一两条错误旧事,以防运用顺序不克不及掀开那个旧事文件大概查询旧事表。
- 防范非 Unicode 字符集之间的译码,以防损掉目的字符汇集没有的字符。
- 对于不是用 Java 言语编写的运用顺序,在运用顺序情况中用分歧的码页对它举办测试。您大概不克不及节制用户的码页。(Java 运用顺序码页老是 UTF-16。)
- 用一些非 ASCII 数据测试运用顺序。码页 437、 1252、8859-1 和 1208(UTF-8 的编码)在前 128 个字节中都与 US-ASCII 婚配,所以 US-ASCII 数据在编码或译码方面出成果的几率更小。搜检在译码时损掉的字符,这平日不会孕育产生任何错误旧事。
- 运用通用 DB2 Driver for JDBC and SQLJ,而不是遗留的 Type 2 驱动顺序。假定不克不及节制运用顺序所运用的驱动顺序,那么可以用出产中将运用的驱动顺序范例对运用顺序举办测试,防范那些不是在齐备驱动顺序范例中都能事情大概在分歧驱动顺序中有分歧举动的体例。
- 对于 C 运用顺序,为了处理
char[]
数据范例中的 XML,运用 UTF-8 编码,因为它不包括 null(\0
)作为有效字节。 - 对于 CLI 和 ESQL 运用顺序,要清晰 CLI 会前去运用外部编码的 XML 数据。假定举办译码,大概改动理论编码,则文档变得不成用。为了防范这一点,将运用顺序变量绑定到
SQL_C_BINARY
范例;这样可以使数据贯穿连接运用 UTF 编码,从而防范从今后编码到外埠码页的有损掉的译码。 - 对于将寄存 UTF 字符的任何数据范例,要供应充沛的空间,因为一个字符大体占多个字节。
版权声明: 原创作品,容许转载,转载时请务必以超链接体例标明文章 原始原因 、作者信息和本声明。不然将究查司法责任。