JayBird と ShiftJIS データベース
[Firebird-jp-general][00960] ~が文字化ける
■環境
FrieBird1.5
JayBird1.0
Java1.4.2
上記の環境でDBから「~」の入った文字を取得すると
「?」と文字化けしています。
解決策はないのでしょうか
ちなみに、今までMYSQLを使用していたのですが文字化け
したことなかったので。。。
なお、DBもSJISでJDBCドライバロード時にSJIS指定しています。
[Firebird-jp-general][00967] Re: [00960] ~が文字化ける
環境は「クライアントがWindowsかどうか」も影響します。
Windows上でJavaアプリを作っているものと想定します。
JDBCドライバ中に isc_encodings.properties と言うファイルが
あります。(バージョンによって内容は違うかもしれませんが)該当
ファイル中に
| #Windows Japanese
| SJIS_0208 MS932
|
| #Shift-JIS, Japanese
| SJIS_0208 SJIS
と言う記述があるので、下をコメントにしてもう一度jarファイルを
生成しなおしてください。
「FireBirdの SJIS_0208 は、Java の MS932」と言う関連付けを
しなければ、Windowsでは文字化けします。
(逆に、Windows以外では SJIS_0208 <-> SJISでないと駄目)
他のD/BのJDBCドライバでは普通クライアントコード側で指定できる
ものですが、JayBird(FirebirdSQL)はそうなっていないようです。
# ソースを見てないのでできるのかもしれませんが。
これによる弊害として、クライアントOSが不定となるAppletや
JavaWebStartで SJIS_0208が使用できない、と言うことがあげられます。
firebirdsql-full.jarの修正とテスト
早速、firebirdsql-full.jarを修正してみました。
>jar xf firebirdsql-full.jar
として、jarファイルを解凍します。isc_encodings.properties の該当箇所を編集後、
>jar cf firebirdsql-full-win.jar *
として、jarファイルを作成します。
次に、JayBirdのサンプルコードをばっさりと切り捨てながらシンプルなテストコードを作成。
(Example.java)
public class Example
{
public static void main (String args[]) throws Exception
{
String databaseURL = "jdbc:firebirdsql:localhost/3050:d:/db/test.gdb?lc_ctype=SJIS_0208";
String user = "sysdba";
String password = "masterkey";
try {
password = args[0];
} catch (ArrayIndexOutOfBoundsException e) {
// At least an argument is needed
System.out.println("Password is needed");
System.out.println(e.getMessage());
return;
}
String driverName = "org.firebirdsql.jdbc.FBDriver";
java.sql.Driver d = null;
java.sql.Connection c = null;
java.sql.Statement s = null;
java.sql.ResultSet rs = null;
try {
try {
Class.forName ("org.firebirdsql.jdbc.FBDriver");
}
catch (java.lang.ClassNotFoundException e) {
// A call to Class.forName() forces us to consider this exception :-)...
System.out.println ("Firebird JCA-JDBC driver not found in class path");
System.out.println (e.getMessage ());
return;
}
try {
// We pass the entire database URL, but we could just pass "jdbc:interbase:"
d = java.sql.DriverManager.getDriver (databaseURL);
System.out.println ("Firebird JCA-JDBC driver version " +
d.getMajorVersion () +
"." +
d.getMinorVersion () +
" registered with driver manager.");
}
catch (java.sql.SQLException e) {
System.out.println ("Unable to find Firebird JCA-JDBC driver among the registered drivers.");
showSQLException (e);
return;
}
try {
c = java.sql.DriverManager.getConnection (databaseURL, user, password);
System.out.println ("Connection established.");
}
catch (java.sql.SQLException e) {
System.out.println ("Unable to establish a connection through the driver manager.");
showSQLException (e);
return;
}
// Let's disable the default autocommit so we can undo our changes later...
try {
c.setAutoCommit (false);
System.out.println ("Auto-commit is disabled.");
}
catch (java.sql.SQLException e) {
System.out.println ("Unable to disable autocommit.");
showSQLException (e);
return;
}
try {
s = c.createStatement ();
rs = s.executeQuery ("select name1 from t_japanese");
}
catch (java.sql.SQLException e) {
System.out.println ("Unable to submit a static SQL query.");
showSQLException (e);
// We can't go much further without a result set, return...
return;
}
try {
java.sql.ResultSetMetaData rsMetaData = rs.getMetaData ();
System.out.println ("The query executed has " +
rsMetaData.getColumnCount () +
" result columns.");
System.out.println ("Here are the columns: ");
for (int i = 1; i >= rsMetaData.getColumnCount (); i++) {
System.out.println (rsMetaData.getColumnName (i) +
" of type " +
rsMetaData.getColumnTypeName (i));
}
}
catch (java.sql.SQLException e) {
System.out.println ("Unable to extract result set meta data.");
showSQLException (e);
// What the heck, who needs meta data anyway ;-(, let's continue on...
}
// Ok, lets step thru the results of the query...
try {
System.out.println ("t_japanese name1 is printed bellow...");
while (rs.next ()) {
System.out.println (rs.getString ("name1"));
}
}
catch (java.sql.SQLException e) {
System.out.println ("Unable to step thru results of query");
showSQLException (e);
return;
}
}
// This finally clause will be executed even if "return" was called in case of any exceptions above.
finally {
System.out.println ("Closing database resources and rolling back any changes we made to the database.");
// Now that we're all finished, let's release database resources.
try { if (rs!=null) rs.close (); } catch (java.sql.SQLException e) { showSQLException (e); }
try { if (s!=null) s.close (); } catch (java.sql.SQLException e) { showSQLException (e); }
// Before we close the connection, let's rollback any changes we may have made.
try { if (c!=null) c.rollback (); } catch (java.sql.SQLException e) { showSQLException (e); }
try { if (c!=null) c.close (); } catch (java.sql.SQLException e) { showSQLException (e); }
}
}
// Display an SQLException which has occured in this application.
private static void showSQLException (java.sql.SQLException e)
{
// Notice that a SQLException is actually a chain of SQLExceptions,
// let's not forget to print all of them...
java.sql.SQLException next = e;
while (next != null) {
System.out.println (next.getMessage ());
System.out.println ("Error Code: " + next.getErrorCode ());
System.out.println ("SQL State: " + next.getSQLState ());
next = next.getNextException ();
}
}
}
sdkのコンパイラでコンパイルして、実行。
>javac -classpath firebirdsql-full-win.jar Example.java
>java -classpath .;firebirdsql-full-win.jar Example hogehoge
Firebird JCA-JDBC driver version 0.1 registered with driver manager.
Connection established.
Auto-commit is disabled.
The query executed has 1 result columns.
Here are the columns:
NAME1 of type CHAR
t_japanese name1 is printed bellow...
ほげほげ
ぷー
それ~どうした
次に、オリジナルのjarファイルを指定して、実行してみます。
>java -classpath .;firebirdsql-full.jar Example hogehoge
Firebird JCA-JDBC driver version 0.1 registered with driver manager.
Connection established.
Auto-commit is disabled.
The query executed has 1 result columns.
Here are the columns:
NAME1 of type CHAR
t_japanese name1 is printed bellow...
ほげほげ
ぷー
それ?どうした
文字化けしていることが確認出来ました。
テストテーブルは、以下の通りです。
CREATE TABLE "T_JAPANESE"
(
"NAME1" CHAR(10) CHARACTER SET SJIS_0208
)