• Thứ Sáu, 15/12/2006 08:40 (GMT+7)

    Java và Unicode

    Câu hỏi :
    Tôi lập trình bằng Java (JBuilder2005). Trong chương trình có một ô soạn thảo là đối tượng của JEditorPane dùng font tiếng Việt Unicode. Tôi set font cho ô soạn thảo là Tahoma và chọn Encoding là UTF8. Khi chạy chương trình và gõ vào thì hiển thị tiếng Việt tốt. Sau đó tôi dùng Jdbc:Odbc:... để lưu lại nội dung của ô soạn thảo này vào một table của Access. Trong table tôi khai báo field này kiểu Memo. Tuy nhiên khi vào Access để xem dữ liệu thì các chữ tiếng Việt có dấu đều biến thành dấu hỏi (?). Tôi lại thử gõ trực tiếp tiếng Việt vào field này thì hiển thị đúng. Liệu có phải trong quá trình chuyển đổi từ kiểu String trong ô soạn thảo của Java sang kiểu Memo của Access, Java đã chuyển các mã 2 byte > 255 của Unicode thành mã 1 byte là dấu hỏi. Nếu đúng như vậy thì làm sao để giải quyết vấn đề? 
     

    Trả lời :

    Mặc dù Unicode là bộ mã chuẩn của Việt Nam lẫn thế giới nhưng hiện các hệ thống và/hoặc các ứng dụng chưa hỗ trợ hoàn toàn bộ mã Unicode. Thí dụ bạn lập trình bằng Java và truy xuất dữ liệu Unicode trong database Access (hay hệ quản trị khác), bạn đã gặp lỗi trong việc đọc/ghi các chuỗi Unicode. Thực vậy, đã có nhiều module phần mềm tham gia việc đọc/ghi dữ liệu giữa ứng dụng Java và database như các hàm tương ứng trong Java, các hàm trong Provider ODBC truy xuất database, các hàm trong chính server database. Do đó việc xác định lỗi nằm chính xác trong hàm xử lý nào là chuyện khá phức tạp. Hiện nay, cách tốt nhất để đọc/ghi chuỗi Unicode với database là ứng dụng chuyển chuỗi Unicode thành mã UTF8 trước khi ghi nó lên database. Tương tự, mỗi khi đọc dữ liệu chuỗi từ database, ứng dụng sẽ chuyển nó từ UTF8 về mã Unicode để xử lý tiếp. Do mã UTF8 tương thích hoàn toàn với các ứng dụng cũ dùng bộ mã 8 bit nên sẽ khắc phục được lỗi mà bạn trình bày.

     Sau đây là qui trình xây dựng ứng dụng Java demo việc ghi/đọc chuỗi Unicode giữa database Access và các TextBox Java:
     • chạy JBuilder, tạo 1 Project mới, tạo 1 ứng dụng mới chứa 1 form giao diện trống.
     • vẽ 3 Textbox chứa họ tên, địa chỉ, năm sinh của từng người với tên nhận dạng lần lượt là jtxtHoten, jtxtdiachi, jtxtNamsinh.
     • vẽ 2 button để ra lệnh Lưu/đọc dữ liệu giữa các textbox và database với tên lần lượt là jbtnWrite và jbtnRead, tạo hàm xử lý sự kiện click chuột vào từng button rồi viết code cho từng hàm như sau:
     //hàm xử lý button Lưu
     public void jbtnWrite_actionPerformed(ActionEvent e) {
     String url = "c:\\Mydata\\MyDataBase.mdb";
     //xây dựng chuỗi ConnectionString
     String conStr = "jdbc:odbc:Driver={Microsoft Access Driver (*.mdb)};DBQ="+url;
     Connection con;
     try {
     Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
     //tạo Connection truy xuất database
     con = DriverManager.getConnection(conStr,"","");
     //tạo đối tượng Statement để truy xuất database
     Statement stmt = con.createStatement();
     //chuyển các chuỗi của 3 textbox về mã UTF8.
     byte[] utf8Bytes = jtxtData.getText().getBytes("UTF8");
     String hoten = new String(utf8Bytes, "Cp1252");
     utf8Bytes = jtxtDiachi.getText().getBytes("UTF8");
     String diachi = new String(utf8Bytes, "Cp1252");
     int namsinh = Integer.parseInt(jtxtNamsinh.getText());
     //tạo mới 1 bảng tên là DSHocsinh.
     stmt.executeUpdate("create table DSHocsinh (hoten varchar(30), diachi varchar(50), namsinh int);");
     
     //thêm record dữ liệu vào table.
     stmt.executeUpdate("insert into DSHocsinh values ('" + hoten + "', '"+diachi+"', "+namsinh+");");
     //xóa đối tượng stmt và con đang dùng.
     stmt.close(); con.close();
     } catch(Exception ex){
     System.out.println("Error : "+ex);
     }
     }
     
     //hàm xử lý button Read
     public void jbtnRead_actionPerformed(ActionEvent e) {
     String url = "c:\\Mydata\\MyDataBase.mdb";
     //xây dựng chuỗi ConnectionString
     String conStr = "jdbc:odbc:Driver={Microsoft Access Driver (*.mdb)};DBQ="+url;
     Connection con;
     String newSQL="SELECT * FROM DSHocsinh";
     try {
     Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
     //tạo Connection truy xuất database
     con = DriverManager.getConnection(conStr,"","");
     //tạo đối tượng Statement để truy xuất database
     Statement stmt = con.createStatement();
     //tìm tất cả record trong table DSHocsinh
     ResultSet rs = stmt.executeQuery(newSQL);
     if (rs != null) while (rs.next()){
     //chuyển các chuỗi trong record đầu tiên và hiển thị
     String hoten = rs.getString("hoten");
     byte[] utf8Bytes = hoten.getBytes("Cp1252");
     jtxtData.setText(new String(utf8Bytes, "UTF8"));
     String diachi = rs.getString("diachi");
     utf8Bytes = diachi.getBytes("Cp1252");
     jtxtDiachi.setText(new String(utf8Bytes, "UTF8"));
     jtxtNamsinh.setText(rs.getString("namsinh"));
     break;
     }
     //xóa đối tượng stmt và con đang dùng.
     rs.close(); stmt.close(); con.close();
     } catch(Exception ex){
     System.out.println("Error : "+ex);
     }
     }
     

    Chuyên mục: Lập trình