首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> JSP 程式設計 >> 關於JSP

JSP 連接 Sybase 數據庫中文亂碼徹底解決方案

     編輯:關於JSP

問題現象

  • Sybase 運行於 Unix/Linux,字符集未知或非 UTF-8 (如 cp850、eucgb)
  • JSP 頁面 pageEncoding="UTF-8"、Tomcat URIEncoding="UTF-8" 均已設置
  • 常規 new String(bytes, "ISO-8859-1", "GBK") 轉碼無效
  • 查詢結果中文顯示為亂碼 (如 、????、亂碼字符)

根因分析

核心原因:JDBC 驅動在建立連接時未正確聲明字符集,導致驅動按默認編碼 (通常 ISO-8859-1) 解析數據庫返回的字節流。後續在 Java 層轉碼屬於「二次轉碼」,原始字節流已損壞,無法恢復。

關鍵差異:MySQL/PostgreSQL 等現代驅動支持連接參數 characterEncoding 自動轉碼;Sybase jConnect 驅動必須在 JDBC URL 中顯式指定 charset 參數,否則不進行任何轉換。

解決方案:JDBC URL 顯式指定字符集

1. 確定數據庫字符集

在 Sybase 中執行:

sp_configure "default character set id"
-- 或
select @@charset

常見值:

  • cp850 (Western European)
  • eucgb (GB2312/EUC-CN)
  • utf8 (UTF-8)
  • gbk (GBK)

2. 構建正確的 JDBC URL


// 模板
jdbc:sybase:Tds:hostname:port/dbname?charset=DB_CHARSET&jconnect_version=VERSION

// 實例 1:數據庫字符集為 eucgb (GB2312),jConnect 7+
String url = "jdbc:sybase:Tds:192.168.1.100:5000/mydb?charset=eucgb&jconnect_version=7";

// 實例 2:數據庫字符集為 cp850,jConnect 6
String url = "jdbc:sybase:Tds:sybase-host:4100/proddb?charset=cp850&jconnect_version=6";

// 實例 3:數據庫已為 UTF-8
String url = "jdbc:sybase:Tds:localhost:5000/testdb?charset=utf8&jconnect_version=7";

關鍵參數說明:

  • charset:必須與數據庫實際字符集一致,驅動據此將接收字節流解碼為 Java Unicode 字符串
  • jconnect_version:匹配驅動版本 (4/5/6/7),影響協議細節

3. 完整連接代碼示例

<%@ page import="java.sql.*" %>
<%
    String url = "jdbc:sybase:Tds:192.168.1.100:5000/mydb?charset=eucgb&jconnect_version=7";
    String user = "sa";
    String pwd = "password";

    Connection conn = null;
    Statement stmt = null;
    ResultSet rs = null;

    try {
        Class.forName("com.sybase.jdbc4.jdbc.SybDriver"); // jConnect 7
        // Class.forName("com.sybase.jdbc3.jdbc.SybDriver"); // jConnect 6

        conn = DriverManager.getConnection(url, user, pwd);
        stmt = conn.createStatement();
        rs = stmt.executeQuery("SELECT name, description FROM products WHERE id = 1");

        if (rs.next()) {
            // 直接使用 getString(),驅動已按 charset 正確解碼
            String name = rs.getString("name");
            String desc = rs.getString("description");
            out.println("產品: " + name + "
描述: " + desc); } } catch (Exception e) { e.printStackTrace(); out.println("錯誤: " + e.getMessage()); } finally { // 標準資源關閉 try { if (rs != null) rs.close(); } catch (Exception ignore) {} try { if (stmt != null) stmt.close(); } catch (Exception ignore) {} try { if (conn != null) conn.close(); } catch (Exception ignore) {} } %>

驗證與調試步驟

  1. 檢查驅動版本:確保 jconnect_version 與 sybdriver.jar 版本匹配 (jConnect 6/7/16/17 常見)
  2. 測試字符集:用 SQuirreL SQL / DbVisualizer 等工具連接,嘗試不同 charset 參數查看中文顯示
  3. 抓包分析:Wireshark 抓取 TDS 協議包,確認數據庫返回原始字節序列
  4. 日誌調試:啟用 jConnect 詳細日誌 -Djconnect.debug=true 觀察字符集協商過程

避坑指南:常見錯誤做法

錯誤做法為何無效
Java 層 new String(rs.getBytes("col"), "ISO-8859-1", "GBK")驅動已按錯誤編碼將字節解碼為 char[],再 getBytes 丟失原始字節
只設置 JSP pageEncoding / Tomcat URIEncoding只影響 HTTP 響應編碼,不影響 JDBC 驅動解碼
連接池配置未傳遞 charset 參數Druid/HikariCP url 屬性必須包含完整 JDBC URL 含 charset
假設數據庫為 UTF-8 實為 GBKcharset 參數與實際不符,解碼錯誤產生亂碼

進階:連接池配置示例 (Druid)



    
    
    
    
    
    
    
    

總結

  1. 核心動作:JDBC URL 加 ?charset=實際DB字符集 (如 eucgb、cp850、utf8)
  2. 匹配版本:jconnect_version 與驅動 jar 版本一致
  3. 無需轉碼:正確設置後,直接 rs.getString() 即得正確中文
  4. 驗證手段:獨立 SQL 客戶端先驗證 charset 參數再接入代碼
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved