如何通过 Java 从 MS Access 2007 数据库中读取 Unicode 字符?

Posted

技术标签:

【中文标题】如何通过 Java 从 MS Access 2007 数据库中读取 Unicode 字符?【英文标题】:How do I read Unicode characters from an MS Access 2007 database through Java? 【发布时间】:2010-05-09 10:02:37 【问题描述】:

在 Java 中,我编写了一个读取 UTF8 文本文件的程序。该文本文件包含一个 SELECT 类型的 SQL 查询。然后程序在 Microsoft Access 2007 数据库上执行查询并将第一行的所有字段写入 UTF8 文本文件。

我遇到的问题是当返回包含 unicode 字符的行时,例如“♪”。这些字符显示为“?”在文本文件中。

我知道文本文件的读写是正确的,因为从包含 SQL 查询的文本文件中读取了一个伪 UTF8 字符(“◎”),并将其写入到包含结果行的文本文件中。在记事本中打开写入的文本文件时,UTF8 字符看起来是正确的,因此文本文件的读写不是问题的一部分。

这是我连接数据库和执行 SQL 查询的方式:

Connection c = DriverManager.getConnection("jdbc:odbc:Driver=Microsoft Access Driver (*.mdb, *.accdb);DBQ=C:/database.accdb;Pwd=temp");

ResultSet r = c.createStatement().executeQuery(sql);

我尝试为 Connection 设置一个 charSet 属性,但没有任何区别:

Properties p = new Properties();
p.put("charSet", "utf-8");
p.put("lc_ctype", "utf-8");
p.put("encoding", "utf-8");
Connection c = DriverManager.getConnection("...", p);

尝试使用“utf8”/“UTF8”/“UTF-8”,没有区别。如果我输入“UTF-16”,则会出现以下异常:

java.lang.IllegalArgumentException: 非法替换

已经搜索了几个小时没有结果,现在把希望寄托在你身上。请帮忙!

我也接受解决方法建议。 =) 我想要做的是进行 Unicode 查询(例如,搜索包含“あ”字符的帖子)并正确接收和保存带有 Unicode 字符的结果。

谢谢!


更新。这是该问题的一个独立示例:

package test;
import java.io.BufferedReader;import java.io.File;import java.io.FileInputStream;import java.io.FileOutputStream;import java.io.InputStreamReader;import java.io.OutputStreamWriter;import java.nio.charset.Charset;import java.sql.Connection;import java.sql.DriverManager;import java.sql.ResultSet;import java.util.Properties;
public class Standalone 
    public static void main(String[] args) 
        try 
            Properties p = new Properties();
            p.put("charSet", "UTF8");
            Connection c = DriverManager.getConnection("jdbc:odbc:Driver=Microsoft Access Driver (*.mdb, *.accdb);DBQ=./dummy.accdb;Pwd=pass", p);
            ResultSet r = c.createStatement().executeQuery("SELECT TOP 1 * FROM main;");
            r.next();
            OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream(new File("results.txt")), Charset.forName("UTF-8"));
            osw.write(new BufferedReader(new InputStreamReader(new FileInputStream("utf8.txt"), Charset.forName("UTF-8"))).readLine() +" : "+ r.getString("content"));
            osw.close();
            c.close();
            System.out.println("Done.");
         catch (Exception e) 
            e.printStackTrace();
        
    

该示例的作用是打开使用密码“pass”加密的数据库“dummy.accdb”,并将第一个帖子从表“main”中拉出。然后它读取文本文件“utf8.txt”并写入一个文本文件“results.txt”,其中将包含“utf8.txt”的第一行加上它从数据库中获得的“content”字段的值。

在“utf8.txt”文件中,我存储了“♜♞♝♛♚♝♞♜♟♖♘♗♕♔♗♘♖♙”。 在数据库的“主”表的“内容”字段中,我存储了“♫♪あキタℳℴℯ♥∞۞♀♂”。

应用程序运行完毕后,“results.txt”有以下内容:“♜♞♝♛♚♝♞♜♟♖♘♗♕♔♗♘♖♙:?????萌?8?? ?”。

成功读写“utf8.txt”文本文件的UTF8字符,但未能从数据库中获取正确的字符。这就是问题所在。


更新。我想我应该提到数据库中的字段属于“备忘录”类型,我尝试将“Unicode 压缩”设置为“否”和“是”(在尝试之间重新创建帖子以确保没有压缩存在选择“否”)。据我了解,Access 在保存 Unicode 字符时使用 UTF-16,但压缩后会更改为 UTF-8。无论如何,这没有任何区别。

额外的问题,有人知道如何在 Java 中使用纯 ODBC 提供程序连接到数据库吗?或者其他什么方法?这将为我提供一个很好的解决方法。


更新。我一直在尝试将这四个提供给 getConnection:

"Provider=Microsoft.Jet.OLEDB.4.0;Data Source=./dummy.accdb"
"jdbc:odbc:Provider=Microsoft.Jet.OLEDB.4.0;Data Source=./dummy.accdb"
"jdbc:odbc:Driver=Microsoft.Jet.OLEDB.4.0;Data Source=./dummy.accdb"
"jdbc:odbc:Provider=Microsoft.ACE.OLEDB.12.0;Data Source=./dummy.accdb"

第一个给出错误“java.sql.SQLException: No proper driver found for Provider=Microsoft.Jet.OLEDB.4.0;Data Source=./dummy.accdb”,中间两个得到“java.sql .SQLException:[Microsoft][ODBC Driver Manager] 未找到数据源名称且未指定默认驱动程序”。最后一个得到“java.sql.SQLException: [Microsoft][ODBC Driver Manager] Data source name too long”。

我不明白 getConnection 想要什么。参数说明如下:“url - 一个jdbc:subprotocol:subname形式的数据库url”。嗯?我显然不明白这意味着什么。

任何人都知道通过 Java 连接到 Access 2007 数据库的其他工作方式吗?也许我尝试的提供程序不受支持,但其他一些可能是?

【问题讨论】:

您需要发布一个简约的、独立的示例来演示该问题,因为根据此处的答案:***.com/questions/1467412/…、p.put("charSet", "UTF8") 应该可以工作,因为您使用的是 JDBC ODBC 桥 (java.sun.com/j2se/1.4.2/docs/guide/jdbc/bridge.html)。在文件方面,你说你确定文件是用 UTF8 编写的(你必须故意这样做;Java 的默认值是平台编码,几乎可以肯定不是 UTF8)。 @Crowder:“这几乎肯定不是 UTF8”适用于 Windows。大多数现代 Linux 发行版都使用 UTF-8。我知道这与问题没有直接关系,我只是想避免任何人将其视为在所有情况下都是正确的陈述。 @T.J. Crowder:好的,我已经做了一个独立的例子,只是想弄清楚如何与你们分享。 原始帖子已被编辑以包含示例,请查看并给我您的意见。非常感谢。 @T.J Crowder:顺便说一句,你指的答案是指java.sun.com/j2se/1.4.2/docs/guide/jdbc/bridge.html那篇文章已经过时了,可能是五年前写的(底部的版权声明是2002年) .今天该文章中使用的一些关键类无法使用,例如“sun.jdbc.odbc.JdbcOdbcDriver”、“sun.jdbc.odbc.ee.DataSource”和“sun.jdbc.odbc.ee.ConnectionPoolDataSource”。他们要么有访问限制,要么根本无法解决。设置“charSet”在过去可能有用过一次,但很遗憾今天没有用。 【参考方案1】:

在 Access 中使用 jdbc 的替代方法是 Jackcess 库。使用这个库的优点是没有问题的翻译层(如 odbc)或任何外部系统依赖项。使用这个库的缺点是它不支持执行查询。

【讨论】:

【参考方案2】:

由于您提到可以切换到 Access 以外的其他数据库,因此我敦促您这样做。在 Microsoft Office 产品上制作您的软件对我来说一直是维护的噩梦,因此请从此列表中选择其他任何内容:http://java-source.net/open-source/database-engines。

为此,我会使用 Apache Derby,或者只使用随任何当前 Sun Java 安装预装的 Java 数据库 JavaDB(实际上是重新打包的 Derby DB)

【讨论】:

【参考方案3】:

现在 JDBC-ODBC 桥已从 Java SE 8 中删除,并且 Oracle 已确认此问题将永远无法修复(参考:here)一个不错的选择是使用UCanAccess。有关详细信息,请参阅

UCanAccess on SourceForge

Manipulating an Access database from Java without ODBC

【讨论】:

【参考方案4】:

不支持utf-8:

http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6345277

【讨论】:

以上是关于如何通过 Java 从 MS Access 2007 数据库中读取 Unicode 字符?的主要内容,如果未能解决你的问题,请参考以下文章

如何通过编码将数据从 MS Access 导入 Sql Server [关闭]

如何通过 MS ACCESS 表执行 SQL Server 表的批量更新

尝试从 MS Access DB 检索字段值时,Java 中的希腊词作为问号 [重复]

如何从 ADO 记录集字段将图片加载到 MS-Access Image 控件中?

如何通过 Python 3.5.1 创建永久 MS Access Query?

从 JAVA 访问存储在 MS-Access 数据库中的日期/时间数据