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 驱动连接字符编码的主要内容,如果未能解决你的问题,请参考以下文章
为啥 Informix JDBC 驱动程序处理不相关的连接字符串?
MySQLSQLServerMySQL中JDBC驱动和连接字符串