无论是不是使用 UTF8 编码,Postgresql/JDBC 都会失败

Posted

技术标签:

【中文标题】无论是不是使用 UTF8 编码,Postgresql/JDBC 都会失败【英文标题】:Postgresql/JDBC fails with or without UTF8 encoding无论是否使用 UTF8 编码,Postgresql/JDBC 都会失败 【发布时间】:2021-01-07 04:50:33 【问题描述】:

使用 Java 8 和 Postgres 10 服务器,以及 v 42.2.16 Postgresql 驱动程序, 我有一个基本的 JDBC 查询函数:

public List<Map<String, Object>> Query(String sql) throws Exception 
    Connection con = null ;
    PreparedStatement pstmt;
    List<Map<String, Object>> resultSetToList = null;
    try 
        
        con = DriverManager.getConnection(ConnectionString, Properties);
        pstmt = con.prepareStatement( sql );
        pstmt.execute();
        
        ResultSet resultSet = pstmt.getResultSet();
        resultSetToList = resultSetToList(resultSet);

        pstmt.close();

     catch(Exception e)
        throw e;
    
        finally 
    
        if (con != null)
            con.close();
    
    return resultSetToList;

我执行这样的查询:

Query("SELECT * FROM bi_functions");

但是会抛出异常

org.postgresql.util.PSQLException: ERROR: invalid byte sequence for encoding "UTF8": 0xa3

数据库(由第 3 方提供)编码为 SQL_ASCII。 0xA3 是“英镑”字符。

所以我将查询更改为:

SET LOCAL CLIENT_ENCODING TO 'SQL_ASCII'; SELECT * FROM bi_functions;

它失败了:

org.postgresql.util.PSQLException:服务器的 client_encoding 参数已更改为 SQL_ASCII。 JDBC 驱动程序要求 client_encoding 为 UTF8 才能正确操作。

有没有办法使用普通的 JDBC 来规避这个错误?

【问题讨论】:

不,你不能那样做。有趣的问题是:服务器编码是什么,数据库中存储了哪些字节? DB(由第 3 方提供)已编码 SQL_ASCII。 0xA3 是“英镑”字符。你是说我不能通过 JDBC 读取这个数据库? 【参考方案1】:

Java 在内部使用 Unicode 编码,因此您不能在 JDBC 驱动程序中使用不同于 UTF8client_encoding

您应该弄清楚数据库的实际编码(可能是 ISO 8859 或 Windows 编码之一)。然后使用该编码创建一个数据库并转储原始数据库并将转储的数据库加载到其中。

否则您将无法将此数据库与 JDBC 一起使用。

【讨论】:

在第三方服务器上,DB被列为Encoding SQL_ASCII;整理 en_GB;字符类型 en_GB。还有另一种方法来确定“实际编码”吗?它是一个 Windows 服务器,所以可能是 1252 编码。如果我使用该编码在本地创建数据库,通过 JDBC 查询时会不会遇到同样的问题? 如果数据库中的所有数据都与Windows-1252一致,就没有问题。如果不是(例如,某些 UTF-8 数据已潜入),则您必须修复数据库中的数据。 我正在 Mac (Catalina) 服务器上恢复数据库 - 这有什么不同吗? 不,平台不应该有所作为。 将备份恢复到使用 ENCODING = 'WIN1252' 创建的数据库有效,谢谢

以上是关于无论是不是使用 UTF8 编码,Postgresql/JDBC 都会失败的主要内容,如果未能解决你的问题,请参考以下文章

utf8_encode 不是编码/转换字符

java判断字符串是不是超出utf8编码

MySQL编码latin1转utf8

客户编码在utf8而不是unicode

MySQL设置默认编码集为utf8怎么设置

如何检查字符串是不是是UTF8编码