在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: Illegal replacement
一直在寻找没有结果的时间,现在转向我的希望。请帮忙!
我也接受解决方法建议。 =)我想要做的是创建一个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”具有以下内容:“♜♞♝♛♚♝♞♜♟♖♘♗♕♔♗♘♖♙:???????????????????????? ?”。
它成功读取和写入“utf8.txt”文本文件的UTF8字符,但无法从数据库中获取正确的字符。这就是问题所在。
更新。我想我应该提到数据库中的字段是“memo”类型,我已经尝试过havig“Unicode Compression”设置为“No”和“Yes”(重新尝试之间的帖子以确保没有压缩存在当选择“否”时)。据我所知,Access在保存Unicode字符时使用UTF-16,但是对其进行压缩会更改为UTF-8。无论如何,这没有任何区别。
Bonus问题,任何人都知道如何使用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:没有为Provider发现合适的驱动程序= Microsoft.Jet.OLEDB.4.0;数据源=。/ dummy.accdb”并且中间的两个获取“java.sql” .SQLException:[Microsoft] [ODBC驱动程序管理器]未找到数据源名称且未指定默认驱动程序“。最后一个得到“java.sql.SQLException:[Microsoft] [ODBC Driver Manager]数据源名称太长了”。
我不明白getConnection想要什么。参数说明如下:“url - jdbc:subprotocol:subname形式的数据库URL”。咦?我显然不明白这意味着什么。
任何人都知道通过Java连接到Access 2007数据库的任何其他工作方式吗?也许我试过的提供商不受支持,但其他一些可能会支持?
答案 0 :(得分:2)
使用jdbc和Access的替代方法是Jackcess库。使用这个库的专家是没有有问题的翻译层(如odbc)或任何外部系统依赖。使用这个库的原因是它不支持执行查询。
答案 1 :(得分:1)
由于您提到切换到除Access之外的其他数据库,我建议您这样做。在Microsoft Office产品上制作软件一直是我的维护噩梦,因此请从此列表中选择其他任何内容:http://java-source.net/open-source/database-engines。
我会选择Apache Derby,或者只使用预装了当前任何Sun Java安装的Java数据库JavaDB(实际上是重新打包的Derby DB)
答案 2 :(得分:1)
现在已经从Java SE 8中删除了JDBC-ODBC Bridge,并且Oracle已经确认永远不会修复此问题(参考:here),一个好的替代方法是使用UCanAccess。有关更多信息,请参阅
答案 3 :(得分:0)