Похоже, ваш исходный файл Java закодирован как UTF-8, поэтому, когда строка cityName
содержит LEÓN
, она кодируется как
L E Ó N
-- -- ----- --
4C 45 C3 93 4E
Это не то, как Access хранит значение. Access хранит символы в формате Unicode, но не использует кодировку UTF-8. Он использует разновидность кодировки UTF-16LE, в которой символы с кодовыми точками U+00FF и ниже хранятся в одном байте, а символы с кодовыми точками выше U+00FF хранятся в виде значения Null (0x0), за которым следует их UTF-16LE. пара байтов. В этом случае Ó
— это U+00D3, что ниже U+00FF, поэтому Access сохраняет все четыре символа строки как одиночные байты:
L E Ó N
-- -- -- --
4C 45 D3 4E
В результате кодировка строки в базе данных Access такая же, как и для набора символов ISO 8859-1.
Это можно подтвердить с помощью следующего кода Java, который использует мост JDBC-ODBC. Не удается найти нужную запись, когда исходный файл Java закодирован как UTF-8
, но он работает, когда исходный файл Java закодирован как cp1252
в Eclipse:
import java.sql.*;
public class accentTestMain {
public static void main(String[] args) {
String connectionString =
"jdbc:odbc:Driver={Microsoft Access Driver (*.mdb, *.accdb)};" +
"DBQ=C:\\__tmp\\test\\accented.accdb;";
try {
Connection con = DriverManager.getConnection(connectionString);
PreparedStatement stmt = con.prepareStatement("SELECT * FROM localities WHERE locName=?");
String cityName = "LEÓN";
stmt.setString(1, cityName);
stmt.execute();
ResultSet rs = stmt.getResultSet();
if (rs.next()) {
System.out.println(String.format("Record found, ID=%d", rs.getInt("ID")));
}
else {
System.out.print("Record not found.");
}
} catch (SQLException e) {
e.printStackTrace();
}
}
}
Если вы можете обойтись поддержкой только символов с диакритическими знаками, представленных в наборе символов cp1252
, тогда вы сможете просто использовать cp1252
в качестве настройки кодировки для исходных файлов Java.
С другой стороны, если вам действительно нужна полная поддержка символов Unicode в базе данных Access, то JDBC-ODBC Bridge не сделает за вас эту работу. Это давняя проблема взаимодействия между JDBC-ODBC Bridge и драйвером Access ODBC, и она не будет исправлена. (Подробнее здесь.)
В этом случае вы можете рассмотреть возможность использования UCanAccess, который является чисто Java-драйвером JDBC для Access. . Соответствующий код, использующий UCanAccess с исходным файлом в кодировке UTF-8, будет
// assumes...
// import java.sql.*;
Connection conn=DriverManager.getConnection(
"jdbc:ucanaccess://C:/__tmp/test/accented.accdb");
PreparedStatement ps = conn.prepareStatement(
"SELECT ID FROM localities WHERE locName=?");
ps.setString(1, "LEÓN");
ResultSet rs = ps.executeQuery();
if (rs.next()) {
System.out.println(String.format(
"Record found, ID=%d",
rs.getInt("ID")));
}
else {
System.out.println("Record not found.");
}
Дополнительные сведения об использовании UCanAccess см. в соответствующем вопросе здесь.
Другим решением может быть использование Jackcess для управления базой данных Access таким образом (опять же, исходный файл Java закодирован как UTF-8):
import java.io.File;
import java.io.IOException;
import com.healthmarketscience.jackcess.*;
public class accentTestMain {
public static void main(String[] args) {
Database db;
try {
db = DatabaseBuilder.open(new File("C:\\__tmp\\test\\accented.accdb"));
try {
Table tbl = db.getTable("localities");
Cursor crsr = CursorBuilder.createCursor(tbl.getIndex("locName"));
if (crsr.findFirstRow(tbl.getColumn("locName"), "LEÓN")) {
System.out.println(String.format("Record found, ID=%d", crsr.getCurrentRowValue(tbl.getColumn("ID"))));
}
else {
System.out.println("Record not found.");
}
} catch (Exception e) {
e.printStackTrace();
} finally {
db.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
person
Gord Thompson
schedule
10.01.2014