【问题标题】:Obtainig illegible characters from uCanAccess result set从 uCanAccess 结果集中获取乱码
【发布时间】:2020-06-12 01:31:02
【问题描述】:

我正在使用西班牙语字符 ñ á é í ó ú 查询旧的 Access 97 数据库。我可以使用 access 很好地读取字符,所以我假设它使用 ISO-8859-1 但是我无法将它们转换为 UTF-8。

不确定我的问题是否与我的连接有关:

public static Connection baseAccess(String base) {
    try {
        java.util.Properties propiedades = new java.util.Properties();
        propiedades.put("charSet", "ISO-8859-1");
        return DriverManager.getConnection(String.format("jdbc:ucanaccess://%s", base),propiedades);
    } catch (SQLException ex) {}
}

或者用我对字符串的解析:

try (ResultSet rs = UtileriaDb.baseAccess(contabilidad).createStatement().executeQuery(sql);){
    while(rs.next()){
        String fromAccess = rs.getString(1);
        System.out.println(fromAccess);
        String transformed = new String(fromAccess.getBytes("ISO-8859-1"),"UTF-8");
        System.out.println(transformed);
    }
} catch (Exception ex) { }

所以当我期望时:

Año 咖啡厅

我明白了:

咖啡厅

A?o 咖啡馆?

尝试通过执行以下操作从结果集中获取字节内容:byte[] fromAccess = rs.getBytes(1);,但出现异常

net.ucanaccess.jdbc.UcanaccessSQLException: UCAExc:::4.0.4 incompatible data type in conversion: from SQL type VARCHAR to [B, value: myText
    at net.ucanaccess.jdbc.UcanaccessResultSet.getBytes(UcanaccessResultSet.java:339)

所以这是一个死胡同。有没有其他方法可以解决?

【问题讨论】:

  • 您是在 CLI 还是 IDE 上运行它? rs的类型是什么?
  • 类型是 java.sql.ResultSet 刚刚更新了问题 sn-p 我正在将 transformed 字符串写入带有 default charset=latin1 的 mySql 表中,并且非 ascii 值也存储为 ?输出来自 netbeans 终端,也将尝试使用 bash 和 cmd
  • 我认为问题出在rs.getString(1); 我会使用byte[] bytes = rs.getBytes(1) 而不是transformed = new String(bytes, 'ISO-8859-1');
  • 好主意!但是我得到了一个 SQLException incompatible data type in conversion: from SQL type VARCHAR to [B, value: myText 。我不认为 ucanaccess 支持它。堆栈跟踪说在net.ucanaccess.jdbc.UcanaccessResultSet.getBytes(UcanaccessResultSet.java:339)
  • 下一个合乎逻辑的步骤将是您的假设“我假设它使用ISO-8859-1”:)

标签: java database character-encoding resultset ucanaccess


【解决方案1】:

正如@Scratte 正确指出的那样,rs.getString(1) 正在返回一个已经包含替换字符的字符串。感谢他帮助我指向this questionthis discussion

我最终实现了一个 ucanaccess JackcessOpenerInterface 并且工作得非常好

package com.company.somepackage;

import com.healthmarketscience.jackcess.Database;
import com.healthmarketscience.jackcess.DatabaseBuilder;
import java.io.File;
import java.io.IOException;
import java.nio.charset.Charset;
import net.ucanaccess.jdbc.JackcessOpenerInterface;

public class CharsetOpener implements JackcessOpenerInterface {
    public Database open(File f, String pwd) throws IOException {
        DatabaseBuilder db = new DatabaseBuilder(f);
        db.setCharset(Charset.forName("ISO-8859-1"));
        try {
            db.setReadOnly(false);
            return db.open();
        } catch (IOException e) {
            db.setReadOnly(true);
            return db.open();
        }
   }
}

对于我的连接生成器中的实现:

public static Connection baseAccess(String base) {
    try {
        java.util.Properties propiedades = new java.util.Properties();
        propiedades.put("jackcessOpener", "com.company.somepackage.CharsetOpener");
        return DriverManager.getConnection(String.format("jdbc:ucanaccess://%s", base),propiedades);
    } catch (SQLException ex) {}
}

注意实际的属性是jackcessOpener,并且必须指向一个完全限定的类名。

【讨论】:

    猜你喜欢
    • 2017-04-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-07-20
    • 2012-08-11
    相关资源
    最近更新 更多