Firebird JDBC 驱动连接字符编码

Posted

技术标签:

【中文标题】Firebird JDBC 驱动连接字符编码【英文标题】:Firebird JDBC driver connection character encoding 【发布时间】:2012-10-20 19:34:46 【问题描述】:

我有一个 JSF 应用程序在 Fedora 17 的 tomcat6 上运行,使用 firebird 作为数据库,从数据库到应用程序的所有寄存器都存在编码问题。

语言是巴西葡萄牙语,所以我需要 é、ã 和 ç,而这里所有这些特殊字符都有问题。

原始源代码中的é和ã是可以的,只有直接来自数据库的那些给我带来了麻烦......

知道发生了什么吗?

这是一个奇怪的字符应该是é的图像

从数据库恢复时会出现问题。

【问题讨论】:

JSF 1.x 还是 2.x?你到底在说哪个“麻烦”?请提供更多细节。你看到的是哪些角色?它究竟在哪一步显示错误的字符?直接在Java代码中从数据库中检索后?还是只在生成的 html 输出中? 什么是DB的默认字符集(或特定的coumns),什么是连接字符集,这些数据是来自BLOB SUB_TYPE TEXT还是(VAR)CHAR? 试图添加更多信息 您仍然不清楚它何时失败。请从开发人员的角度阐述问题,而不是从最终用户的角度。首先,在从数据库中检索数据后直接的代码中,放置一个调试断点或一个记录器或一个 system.out.println,以便您可以调查 JDBC 驱动程序是否已正确解码它。请注意,您应该绝对确保您的 IDE 和 logger/stdout 控制台本身也使用正确的字符集(即您必须能够执行 System.out.println("éãç") 并在控制台中按原样查看)。 请注意,我假设字符已正确存储在数据库中。因此,如果您直接使用一些数据库管理工具查看数据库,这些字符应该看起来不错。否则,首先将其作为 JSF 问题发布是没有意义的。由于您使用的是 JSF 2.x(默认情况下,它本身已经在所有层中使用 UTF-8),我越来越认为问题实际上出在 DB 设置或 JDBC 驱动程序配置中。 【参考方案1】:

在 JDBC 连接 URL 中使用 encoding=ISO/UTF/WIN... 查询参数已经解决了这个问题。

例如:

jdbc:firebirdsql:url:db?encoding=ISO8859_1

【讨论】:

谢谢!我也不得不像这样处理 & 转义 [jdbc:firebirdsql:url:db?roleName=XYZ&encoding=UTF8] 因为 ?仅适用于第一个参数。【参考方案2】:

如果您没有在 Jaybird 中指定连接字符集(属性 encoding 使用 Firebird 字符集名称,或 charSet 使用 Java 字符集名称),那么 Jaybird 会退回到 Firebird 的连接概念字符集NONE,这意味着服务器不会从 (VAR)CHAR 列的存储表示中转写字符并按原样发送其字节。

这意味着 Jaybird 接收到未知字符集中的字节序列。 Jaybird 然后将使用 Java 安装的默认字符集将这些字节转换为字符串。因此,如果 db(或列)字符集与您的 Java 字符集不匹配,那么它可能会产生不正确的结果。更糟糕的是:以这种方式从具有不同默认 java 字符集的不同系统中读取和写入会产生完全的垃圾或音译错误。

解决方案:始终指定显式连接字符集。更好的是确保您的数据库具有默认字符集(或者每个 (VAR)CHAR 列都明确定义了其字符集)。

如果没有指定明确的连接字符集来强制用户考虑这个问题,Jaybird (2.3) 的下一个版本可能会拒绝连接(如果他们仍然想要旧的行为,那么他们可以明确指定 encoding=NONE)。

【讨论】:

【参考方案3】:

自从我通过谷歌来到这里寻找答案以来,我的 2 美分.. 我在使用旧版 jaybird 驱动程序 (v1.5) 时遇到了 interbase 7.5.80 的问题。 除了“NONE”之外,我在连接上使用的任何编码都会导致连接超时。 最终我继续使用'NONE':

FBWrappingDataSource dataSource = new FBWrappingDataSource();
dataSource.setDatabase("url");
dataSource.setType("TYPE4");
dataSource.setEncoding("NONE");
dataSource.setLoginTimeout(10);
java.sql.Connection c = dataSource.getConnection("sysdba", "masterkey");

并在创建具有特定编码的新 String 实例时使用 getBytes:

String column = new String(rs.getBytes("column"), "Windows-1255");

[rs 当然是结果集]

祝你好运!

【讨论】:

以上是关于Firebird JDBC 驱动连接字符编码的主要内容,如果未能解决你的问题,请参考以下文章

JDBC

为啥 Informix JDBC 驱动程序处理不相关的连接字符串?

MySQLSQLServerMySQL中JDBC驱动和连接字符串

SqlClient/OLEDB 驱动程序的连接字符串,如 jdbc:jtds 驱动程序?

DB2的JDBC连接字符串有数据库字符集编码的配置参数吗

DB2的JDBC连接字符串有数据库字符集编码的配置参数吗