java - Java / Postgres / Mybatis - 编码“UTF8”的无效字节序列:0xe3 0xa1 0x54
问题描述
在我们的应用服务器上,DevOps 团队在 Postgres (9.4) DB 中使用 SQL_ASCII 编码。
第 3 方应用程序正在将姓氏插入到 Employee 表中并带有重音字符,例如 Núñez
我的 Java (8) 应用程序是使用 Mybatis (3.2.4) 的 Spring (4.3.15) WebApp
当我的应用程序从 SQL_ASCII 数据库中读取此类姓氏时,我得到:
org.postgresql.util.PSQLException:错误:用于编码“UTF8”的无效字节序列:org.postgresql.core.v3.QueryExecutorImpl.receiveErrorResponse(QueryExecutorImpl.java:2182) 处 org.postgresql.core.v3 处的 0xe3 0xa1 0x54。 QueryExecutorImpl.processResults(QueryExecutorImpl.java:1911) 在 org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:173) 在 org.postgresql.jdbc2.AbstractJdbc2Statement.execute(AbstractJdbc2Statement.java:616) 在 org.postgresql .jdbc2.AbstractJdbc2Statement.executeWithFlags(AbstractJdbc2Statement.java:466) at org.postgresql.jdbc2.AbstractJdbc2Statement.execute(AbstractJdbc2Statement.java:459) at org.apache.tomcat.dbcp.dbcp2.DelegatingPreparedStatement.execute(DelegatingPreparedStatement.java:93 ) 在 org.apache.tomcat.dbcp.dbcp2.DelegatingPreparedStatement.execute(DelegatingPreparedStatement.java:93) 在 jdk.internal.reflect.GeneratedMethodAccessor78.invoke(Unknown Source) 在 java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 在 java.base/java.lang.reflect.Method。在 com.sun.proxy.$Proxy98.execute(未知来源)的 org.apache.ibatis.logging.jdbc.PreparedStatementLogger.invoke(PreparedStatementLogger.java:55) 调用(Method.java:566)
如果我尝试通过以下方式更改 client_encoding:
SET client_encoding = 'SQL_ASCII';
然后我得到错误:
org.postgresql.util.PSQLException:服务器的 client_encoding 参数已更改为 LATIN1。JDBC 驱动程序要求 client_encoding 为 UTF8 才能正确操作。在 org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:1950)
我怎样才能“安全地”从数据库中读取这些字符?
解决方案
allowEncodingChanges=true
您可以尝试allowEncodingChanges=true
在 JDBC 连接 URL 中进行设置吗?(还有characterEncoding
)
allowEncodingChanges = 布尔值
使用 V3 协议时,驱动程序会监控最终用户不应触及的某些服务器配置参数的变化。client_encoding 设置由驱动程序设置,不应更改。如果驱动程序检测到更改,它将中止连接。但是,这种行为有一个合法的例外,即对驻留在服务器文件系统上的文件使用 COPY 命令。指定此文件编码的唯一方法是更改 client_encoding 设置。JDBC 团队认为这是 COPY 命令的失败,并希望将来提供另一种指定编码的方法,但现在有这个 URL 参数。仅当您需要在进行复制时覆盖客户端编码时才启用此选项。
错误消息中的字节为1110 0011
, 1010 0001
,0101 0100
如果存储的数据以 编码ISO-8859-1
,则为ã
, ¡
, T
。
当这个字节流被读取为UTF-8
时,第一个字节中的1110
MSB表示一个3
UTF-8 字节字符(自计数)。
所以接下来的 2 个字节应该以10
MSB开头。但是第 3个字节以01
MSB开头
默认情况下,JDBC
驱动程序正在解码此流UTF-8
并在无效字节流上失败。
假设第三个字节以10
MSB开头,则代码可以正常工作,但它可能会错误地将所有这些3
字节映射到 a single Unicode code point
(假设原始编码不是UTF-8
并且相应的 unicode 代码点具有有效的字符表示)。
推荐阅读
- excel - 循环遍历工作表时遍历列
- python - 使用 MFCC 进行语音识别
- solr - Solr基本认证权限设置
- python - 令牌匹配查询不存在
- c# - 当查询包含“\”时,如何使用 C# 中的 WIQL 执行 VSTS 查询
- c# - 将数据库从 MySQL 迁移到 SQL Server,Entity Framework 仍然尝试使用 MySQL
- numpy - 需要帮助了解 GPU 上的内核传输速度(numba、cupy、cuda)
- android - 如果我把它放在 AppBarLayout 中,为什么 TextInputLayout 颜色不会改变?
- javascript - 脚本部分php(laravel)中的json_encode看不到变量
- batch-file - 从 C:\Windows 文件夹中删除文件