1. 程式人生 > >oracle資料庫字符集為ZHS16GBK插入的韓文日文俄文變成問號

oracle資料庫字符集為ZHS16GBK插入的韓文日文俄文變成問號

最近專案中解析xml存在中文俄文日文韓文等等亂七八槽的外文,在插入資料庫中會亂碼變成問號。

原因:是oracle安裝的資料庫的時候字符集不一樣( select userenv('language') from dual可以檢視),SIMPLIFIED CHINESE_CHINA.ZHS16GBK這種會變成問號,而SIMPLIFIED CHINESE_CHINA.AL32UTF8這種字符集卻可以正常儲存。

嘗試了網上的一些修改環境變數NLS_LANG,以及用nvchar的oracle資料型別卻都不行,存到資料庫都亂碼。最後就只能通過將外文內容轉成十六進位制的位元組碼,最後讀取查詢的時候再將位元組碼轉成原來的內容就行。

public class Test {
    // 字串轉換unicode
    public static String string2Unicode(String string) {
        StringBuffer unicode = new StringBuffer();
        for (int i = 0; i < string.length(); i++) {
            // 取出每一個字元
            char c = string.charAt(i);
            // 轉換為unicode
            unicode.append("\\u" + Integer.toHexString(c));
        }
        return unicode.toString();
    }

    // unicode 轉字串
    public static String unicode2String(String unicode) {
        StringBuffer string = new StringBuffer();
        String[] hex = unicode.split("\\\\u");
        for (int i = 1; i < hex.length; i++) {
            // 轉換出每一個程式碼點
            int data = Integer.parseInt(hex[i], 16);
            // 追加成string
            string.append((char) data);
        }
        return string.toString();
    }

    public static String convert(String str)
    {
        str = (str == null ? "" : str);
        String tmp;
        StringBuffer sb = new StringBuffer(1000);
        char c;
        int i, j;
        sb.setLength(0);
        for (i = 0; i < str.length(); i++)
        {
            c = str.charAt(i);
            sb.append("\\u");
            j = (c >>>8); //取出高8位
            tmp = Integer.toHexString(j);
            if (tmp.length() == 1)
                sb.append("0");
            sb.append(tmp);
            j = (c & 0xFF); //取出低8位
            tmp = Integer.toHexString(j);
            if (tmp.length() == 1)
                sb.append("0");
            sb.append(tmp);

        }
        return (new String(sb));
    }


    public static void main(String[] args) {
        String str = "???";
        System.out.println(convert(str));
        System.out.println(string2Unicode(str));
        System.out.println(unicode2String(convert(str)));
        System.out.println(unicode2String(string2Unicode(str)));
    }

}
// \ub9ac\uad11\uadfc 輸出結果
// \ub9ac\uad11\uadfc
// 리광근
// 리광근

但是我們專案這邊用的是JS查詢,封裝的內部框架,不是去請求Java,所以需要用SQL的函式Function實現oracle函式unistr將Oracle資料庫中的Unicode轉換為原文

CREATE OR REPLACE FUNCTION UnicodeToString(v_unicode_str varchar2)
RETURN nvarchar2 AS
  v_str  nvarchar2(1000) :='';

BEGIN
  begin
    select unistr(REPLACE(v_unicode_str,'\u','\')) into v_str from dual ;
  exception
    when others then
      v_str := '';
  end;
  RETURN v_str;
END UnicodeToString;
函式Function說明:
create or replace function 函式名(引數)

return    返回值型別    as    
定義變數
begin    函式主體    end 

函式Function呼叫:(sql語句,instr判斷有沒有包含\u)

(case
    when instr(internationalname, '\u') = 1 then
        UnicodeToString(internationalname)
    else
        internationalname
end) as internationalname