1. 程式人生 > >解析Java中文亂碼的處理方法

解析Java中文亂碼的處理方法

【引自程式猶如人生的部落格】為什麼說亂碼是中國程式設計師無法避免的話題呢?這個首先要從編碼機制上說起,大家都是中文和英文的編碼格式不是一樣,解碼也是不一樣的!如果中國的程式設計師不會遇到亂碼,那麼只有使用漢語程式設計。漢語程式設計是怎麼回事,我也不大清楚,應該是前年吧!我一朋友給我介紹漢語程式設計,怎麼不錯不錯?當時因為學習忙沒去關注這個,等我閒了,那個朋友不弄這個,問他,他也不說不大清楚,最後自己對這個學習也不了了之了。

我寫這個不是講解中英文之間的差距,解碼等,我是將我在這幾年工作遇到各種各樣的亂碼的解決方法,總結起來,也希望大家能把自己暈倒解決亂碼的方法都說出來,咱們弄一個解決亂碼的“葵花寶典”。

對於Java,由於預設的編碼方式是UNICODE,所以用中文也易出問題,常見的解決是:

String s2 = new String(s1.getBytes(“ISO-8859-1”),”GBK”);

1、utf8解決JSP中文亂碼問題

一般說來在每個頁面的開始處,加入:

<%@ page language="java" contentType="text/html; charset=UTF-8"     pageEncoding="UTF-8"%>

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>

<% request.setCharacterEncoding("UTF-8"); %>

◆charset=UTF-8的作用是指定JSP向客戶端輸出的編碼方式為“UTF-8”;
◆pageEncoding="UTF-8",為了讓JSP引擎能正確地解碼含有中文字元的JSP頁面,這在LINUX中很有效;
◆request.setCharacterEncoding("UTF-8");是對請求進行了中文編碼。

有時,這樣仍不能解決問題,還需要這樣處理一下:

String msg = request.getParameter("message");  String str=new String(msg.getBytes("ISO-8859-1"),"UTF-8");  out.println(st);

2、Tomcat 5.5中文亂碼

只要把%TOMCAT安裝目錄%/   webapps\servlets-examples\WEB-INF\classes\filters\SetCharacterEncodingFilter.class檔案拷到你的webapp目錄/filters下,如果沒有filters目錄,就建立一個。  

2)在你的web.xml里加入如下幾行:

  <filter>   

<filter-name>Set   Character   Encoding</filter-name>   

<filter-class>filters.SetCharacterEncodingFilter</filter-class>   

<init-param>   

<param-name>encoding</param-name>   

<param-value>GBK</param-value>   

</init-param>   

</filter>   

<filter-mapping>   

<filter-name>Set   Character   Encoding</filter-name>   

<url-pattern>/*</url-pattern>   

</filter-mapping>

3)完成

2、get方式的解決辦法

1)開啟tomcat的server.xml檔案,找到區塊,加入如下一行:  

  URIEncoding=”GBK”

完整的應如下:

  <connector     
  port="80"   maxThreads="150"   minSpareThreads="25"   maxSpareThreads="75"   
  enableLookups="false"   redirectPort="8443"   acceptCount="100"   
  debug="0"   connectionTimeout="20000"     
  disableUploadTimeout="true"     
  URIEncoding="GBK"   
  />

2)重啟tomcat,一切OK。

3、xmlHttpRequest中文問題

頁面jsp用的GBK編碼

程式碼:

<%@ page contentType="text/html; charset=GBK"%>

javascript部分

程式碼:

function addFracasReport() {   
    var url="controler?actionId=0_06_03_01&actionFlag=0010";   
    var urlmsg="&reportId="+fracasReport1.textReportId.value;  //故障報告表編號   
           
    var xmlHttp=Common.createXMLHttpRequest();   
    xmlHttp.onreadystatechange = Common.getReadyStateHandler(xmlHttp, 
       eval("turnAnalyPage"));   
    xmlHttp.open("POST",url,true);   
    xmlHttp.setRequestHeader( " Content-Type " , " 
       application/x-www-form-urlencoded);   
    xmlHttp.send(urlmsg);          
}

#p#

後臺java中獲得的reportId是亂碼,不知道該怎麼轉,主要是不知道xmlHttp.send(urlmsg);以後是什麼編碼?在後面用java來轉,試了幾種,都沒有成功,其中有:

程式碼:

public static String UTF_8ToGBK(String str) {   
        try {   
            return new String(str.getBytes("UTF-8"), "GBK");   
        } catch (Exception ex) {   
            return null;   
        }   
    }   
       
    public static String UTF8ToGBK(String str) {   
        try {   
            return new String(str.getBytes("UTF-16BE"), "GBK");   
        } catch (Exception ex) {   
            return null;   
        }   
    }   
       
    public static String GBK(String str) {   
        try {   
            return new String(str.getBytes("GBK"),"GBK");   
        } catch (Exception ex) {   
            return null;   
        }   
    }   
         public static String getStr(String str) {   
        try {   
            String temp_p = str;   
            String temp = new String(temp_p.getBytes("ISO8859_1"), "GBK");   
            temp = sqlStrchop(temp);   
            return temp;   
        } catch (Exception e) {   
            return null;   
        }   
    }

4、JDBC ODBC Bridge的Bug及其解決方法

在編寫一資料庫管理程式時,發現JDBC-ODBC Bridge存在不易發現的Bug。在向資料表插入資料時,如果為英文字元,儲存內容完全正確,如果存入中文字元,部分資料庫只能儲存前七八個中文字元,其他內容被截去,導致儲存內容的不完整(有些資料庫不存在這個問題,如Sybase SQL Anywhere 5.0。JDBC-ODBC Bridge還存在無法建表的Bug)。

對於廣大需要儲存中文資訊的Java程式設計師來說,這可是一個不好的訊息。要麼改用其他語言程式設計,要麼選擇其他價格昂貴的資料庫產品。“一次編寫,到處執行”的目標,也大打折扣。能不能採用變通的方法,將中文資訊進行處理後再儲存來解決這個問題呢?答案是肯定的。

解決問題的具體思路、方法 
  
Java採用Unicode碼編碼方式,中英文字元均採用16bit儲存。既然儲存英文資訊是正確的,根據一定規則,將中文資訊轉換成英文資訊後儲存,自然不會出現截尾現象。讀取資訊時再進行逆向操作,將英文資訊還原成中文資訊即可。由GB2312編碼規則可知,漢字一般為二個高位為1的ASCII碼,在轉換時將一個漢字的二個高位1去掉,還原時再將二個高位1加上。為了處理含有英文字元的中文字串,對英文字元則需要加上一個Byte 0標記。以下提供的兩個公用靜態方法,可加入任何一個類中使用。

將中英文字串轉換成純英文字串

  public static String toTureAsciiStr(String str){ 
  StringBuffer sb = new StringBuffer(); 
  byte[] bt = str.getBytes(); 
  for(int i =0 ;i〈bt.length;i++){ 
  if(bt[i]〈0){ 
  //是漢字去高位1 
  sb.append((char)(bt[i]&&0x7f)); 
   }else{//是英文字元 補0作記錄 
  sb.append((char)0); 
  sb.append((char)bt[i]); 
   } 
   } 
  return sb.toString(); 
  }

將經轉換的字串還原

  public static String unToTrueAsciiStr(String str){    byte[] bt = str.getBytes();    int i,l=0,length = bt.length,j=0;    for(i = 0;i〈length;i++){    if(bt[i] == 0){    l++;    }    }

   byte []bt2 = new byte[length-l];    for(i =0 ;i〈length;i++){    if(bt[i] == 0){    i++;

   bt2[j] = bt[i];    }else{    bt2[j] = (byte)(bt[i]|0x80);    }    j++;    }

  String tt = new String(bt2);   return tt;   }

上例在實際程式設計中效果很好,只是儲存的中文資訊需要經過同樣處理,才能被其他系統使用。而且如果中文字串出現英文字元,實際上增加了額外的儲存空間。

#p#

5、Solaris下Servlet程式設計的中文問題及解決辦法

在使用Java開發Internet上的一個應用系統時,發現在Windows下除錯完全正常的Servlet,上傳到Solaris伺服器上,執行卻出現故障——返回的網頁不能顯示中文,應為中文的資訊全為亂碼;用中文資訊做關鍵字,不能正確檢索資料庫。後來採用加入檢查程式碼等方法探知故障原因如下:

顯示亂碼主要是因為通過類HttpServletResponse提供的方法setContentType無法改變返回給客戶的資料的編碼方式,正確的編碼方式應為GB2312或者GBK,而事實上為預設的ISO8859-1。無法檢索中文資訊則是因為,客戶提交的中文資訊經瀏覽器編碼到達伺服器後,Servlet無法將其正確解碼。

舉例說明顯示亂碼解決方法

Servlet一般通常做法如下:

  public class ZldTestServlet extends HttpServlet { 
  public void doGet (HttpServletRequest request,
      HttpServletResponse response)throws ServletException,IOException{ 
  //在使用 Writer向瀏覽器返回資料前,設定 content-type header,在這裡設定相應的字符集gb2312 
  response.setContentType("text/html;charset=gb2312"); 
  PrintWriter out = response.getWriter(); //* 
  // 正式返回資料 
  out.println("〈html〉〈head〉〈title〉Servlet test〈/title〉〈/head〉" ); 
  out.println("這是一個測試頁!"); 
  out.println("〈/body〉〈/html〉"); 
  out.close(); 
  } 
   ... 
  }

解決頁面顯示亂碼問題,需將*處程式碼換成如下內容:

PrintWriter out = new PrintWriter(new OutputStreamWriter(response.getOutputStream(),"gb2312"));

Solaris中文資訊檢索問題的解決

瀏覽器利用表單向伺服器提交資訊時,一般採用x-www-form-urlencoded 的MIME格式對資料進行編碼。如果使用get方法,引數名稱和引數值經編碼後附加在URL後,在Java中稱作查詢串(query string)。

在Servlet程式中,如果採用ServletRequest的方法getParameter取得引數值,在Solaris環境下,對漢字卻不能正確解碼。因而無法正確檢索資料庫。

在Java 1.2的包——java.net中提供了URLEncode和URLDecode類。類URLEncode提供了按x-www-form-urlencoded格式對給定串進行轉換的方法。類URLEncode則提供了逆方法。

6、Common Mail亂碼問題

common mail是一個小而方便的mail包,他實現了對Java Mail的封裝,使用起來十分的方便,但是我在使用他的時候發現,使用純文字的內容傳送,結果是亂碼,程式碼如下:

public class TestCommonMail {
public static void main(String[] args) throws EmailException, MessagingException {
SimpleEmail email = new SimpleEmail();
email.setCharset("GB2312");
email.setHostName("smtp.163.com");
email.setSubject("test");
email.addTo("[email protected]");
email.setFrom("[email protected]");
email.setMsg("我的測試");
email.setAuthentication("test", "test");
email.send();
}
}

分析了一下commons mail的原始碼找到了原因。原始碼如下:

public class SimpleEmail extends Email { public Email setMsg(String msg) throws EmailException, MessagingException { if (EmailUtils.isEmpty(msg)) { throw new EmailException("Invalid message supplied"); }

setContent(msg, TEXT_PLAIN); return this; } }

Email程式碼片段:

public void setContent(Object aObject, String aContentType) { this.content = aObject; if (EmailUtils.isEmpty(aContentType)) { this.contentType = null; } else { // set the content type this.contentType = aContentType;

// set the charset if the input was properly formed String strMarker = "; charset="; int charsetPos = aContentType.toLowerCase().indexOf(strMarker); if (charsetPos != -1) { // find the next space (after the marker) charsetPos += strMarker.length(); int intCharsetEnd = aContentType.toLowerCase().indexOf(" ", charsetPos);

if (intCharsetEnd != -1) { this.charset = aContentType.substring(charsetPos, intCharsetEnd); } else { this.charset = aContentType.substring(charsetPos); } } } }

email.send();的send方法將呼叫 public void buildMimeMessage() throws EmailException { try { this.getMailSession(); this.message = new MimeMessage(this.session);

if (EmailUtils.isNotEmpty(this.subject)) { if (EmailUtils.isNotEmpty(this.charset)) { this.message.setSubject(this.subject, this.charset); } else { this.message.setSubject(this.subject); } }

// ===================================================== // Start of replacement code if (this.content != null) { this.message.setContent(this.content, this.contentType); } // end of replacement code // ===================================================== else if (this.emailBody != null) { this.message.setContent(this.emailBody); } else { this.message.setContent("", Email.TEXT_PLAIN); }

if (this.fromAddress != null) { this.message.setFrom(this.fromAddress); } else { throw new EmailException("Sender address required"); }

if (this.toList.size() + this.ccList.size() + this.bccList.size() == 0) { throw new EmailException( "At least one receiver address required"); }

if (this.toList.size() > 0) { this.message.setRecipients( Message.RecipientType.TO, this.toInternetAddressArray(this.toList)); }

if (this.ccList.size() > 0) { this.message.setRecipients( Message.RecipientType.CC, this.toInternetAddressArray(this.ccList)); }

if (this.bccList.size() > 0) { this.message.setRecipients( Message.RecipientType.BCC, this.toInternetAddressArray(this.bccList)); }

if (this.replyList.size() > 0) { this.message.setReplyTo( this.toInternetAddressArray(this.replyList)); }

if (this.headers.size() > 0) { Iterator iterHeaderKeys = this.headers.keySet().iterator(); while (iterHeaderKeys.hasNext()) { String name = (String) iterHeaderKeys.next(); String value = (String) headers.get(name); this.message.addHeader(name, value); } }

if (this.message.getSentDate() == null) { this.message.setSentDate(getSentDate()); }

if (this.popBeforeSmtp) { Store store = session.getStore("pop3"); store.connect(this.popHost, this.popUsername, this.popPassword); } } catch (MessagingException me) { throw new EmailException(me); } }

由程式碼可以知道純文字方式最終呼叫了Java Mail的message.setContent(this.content, this.contentType);content是內容,contentType是型別,如text/plain,(我們可以試試直接用Java mail發郵件,設定文字內容不使用setText方法,也使用setContent("測試", "text/plain")方式,你可以看到內容也是亂碼)。關鍵就在於text/plain,我們改成text/plain;charset=gb2312,ok亂碼解決了。在commons mail我們看SimpleEmail類中setMsg方法呼叫的就是setContent(msg, TEXT_PLAIN);我們只需要將Email類中的常量TEXT_PLAIN修改一下加入charset=你的字符集,重新打包jar,這樣就可以了。

#p#

7、toad的字符集的設定與oracle的安裝

oracle資料庫伺服器的安裝一般是中文字符集,有時安裝在不同的平臺下,設定為ISO編碼,toad是oracle開發的最好工具,不是我說的,可是中文環境下安裝的toad,開啟英文字元的oracle時,中文全是亂碼。必須進行設定:

環境變數---〉系統變數

NLS_lANG=SIMPLIFIED CHINESE_CHINA.ZHS16GBK

NLS_lANG=AMERICAN_AMERICA.WE8ISO8859P1

AMERICAN_AMERICA.WE8MSWIN1252

或者

(1)開啟登錄檔,點選HKEY_LOCAL_MATHINE;
(2)再點選Software,再點選ORACLE;
(3)在點選HOME(ORACLE所在目錄);
(4)在登錄檔的右半面有NLS_LANG;
(5)雙擊它,將你想要的覆蓋掉原來的,就可以了;
(6)最好記下舊的,以便可以改回來。

connect sys/chang_on_install
update props$
set value$='ZHS16CGB231280'
where name='NLS_CHARACTERSET';
commit;

這樣就OK了。

8、如何解決GWT(google web toolkit)中文的問題

GWT中文亂碼解決方法

(1)把你要顯示的中文“測試字串”輸入到一個檔案,如:1.txt;
(2)進入命令列,進入1.txt所在的目錄,敲入以下命令:native2ascii.exe 1.txt 2.txt回車。這樣就生成了另外一個檔案2.txt;
(3)2.txt的內容如下:\u6d4b\u8bd5\u5b57\u7b26\u4e32;
(4)然後用上面的編碼,在gwt中使用,就可以了。

9、xmlHttp得到的網頁怎麼是亂碼?

(1)在伺服器端使用WebRequest而不是xmlHttp
(2) 將

StreamReader sr = new StreamReader(stream);

對於簡體中文改成:

StreamReader sr = new StreamReader(stream , Encoding.Default );

對於utf-8改成:

StreamReader sr = new StreamReader(stream , Encoding.UTF8 );

當然,Encoding列舉還有很多其他的成員,對於不同的編碼content-type可以有選擇的應用。

(3)後來我發現無論是content-type是gb2312還是utf-8,用

StreamReader sr = new StreamReader(stream , Encoding.Default );

都可以返回正常的漢字,所以統一的改成Encoding.Default。

最後,在伺服器端從一個url獲得網頁的原始碼的程式碼如下:

///

/// post一個指定的url,獲得網頁的原始碼(用WebRequest實現) /// /// /// /// 如果請求失敗,返回null /// 如果請求成功,返回網頁的原始碼 /// public static string GetContentFromUrl2( string url ) {     //變數定義     string respstr;

    WebRequest myWebRequest=WebRequest.Create(url);     //            myWebRequest.PreAuthenticate=true;     //            NetworkCredential networkCredential=

new NetworkCredential( username , password , domain );     //            myWebRequest.Credentials=networkCredential;

    // Assign the response object of 'WebRequest' to a 'WebResponse' variable.     WebResponse myWebResponse=myWebRequest.GetResponse();     System.IO.Stream stream = myWebResponse.GetResponseStream();     StreamReader sr = new StreamReader(stream , Encoding.Default );     //以字串形式讀取資料流     respstr = sr.ReadToEnd();     sr.Close();          return respstr;        }

相關推薦

解析Java中文亂碼處理方法

【引自程式猶如人生的部落格】為什麼說亂碼是中國程式設計師無法避免的話題呢?這個首先要從編碼機制上說起,大家都是中文和英文的編碼格式不是一樣,解碼也是不一樣的!如果中國的程式設計師不會遇到亂碼,那麼只有使用漢語程式設計。漢語程式設計是怎麼回事,我也不大清楚,應該是前年吧!我一

Java中文亂碼處理

art data- data XML direct 中文亂碼處理 new size tracking 一、處理get方法中文亂碼 方法1 String name = new String(request.getParameter("userName&

Python爬蟲中文小說網點查找小說並且保存到txt(含中文亂碼處理方法)

nbsp nor png erro 請求方式 輸出結果 下載 ros mozilla 從某些網站看小說的時候經常出現垃圾廣告,一氣之下寫個爬蟲,把小說鏈接抓取下來保存到txt,用requests_html全部搞定,代碼簡單,容易上手. 中間遇到最大的問題就是編碼問題,第一抓

log4j日誌檔案中文亂碼處理方法

解決方法:設定編碼格式為:UTF-8,如紅色字型。 #定義DEBUG優先順序,R為日誌輸出目的的 log4j.rootLogger=debug,file #設定日誌輸出型別,為檔案型別 #log4j.appender.file=org.apache.log4j.FileA

java中Filter過濾器處理中文亂碼方法

注意問題:在學習用selvert的過濾器filter處理中文亂碼時,在filter配置初始化時用了utf-8處理中文亂碼,而在提交的jsp頁面中卻用了gbk。雖然兩種都可以出來中文亂碼,但是卻造成了處理亂碼的格式不一致。所以編譯出錯。 解決方法:所有地方都用ut

java實現Servlet的中文亂碼處理

HttpServletRequest:這個物件封裝了客戶端提交過來的一切資料 客戶端提交資料給服務端(這裡指的是在網頁輸入內容提交servlet處理時,在servlet控制檯的輸出亂碼),如果資料中帶有亂碼,可參照如下方法解決: 如果是GET請求(若無亂碼則無需修改) String n

Java Web 中 Servlet 中文亂碼解決方法

Servlet中文亂碼問題解決方法 import java.io.*; import java.net.URLEncoder; import javax.servlet.*; import javax

java判斷字元是否為中文亂碼方法

   中文亂碼在專案中是經常會遇到的情況。當我們通過設定request和response字符集,但是還是出現中文亂碼的時候,今天給介紹一種通過java方法實現判斷string是否為亂碼的方法。 /**

NodeJs伺服器啟動後在瀏覽器訪問時中文顯示亂碼處理方法

建立一個叫 server.js 的檔案,並寫入以下程式碼: //使用 require 指令來載入 http 模組,並將例項化的 HTTP 賦值給變數 http var http=require('h

java中的中文亂碼處理

1.在頁面設定編碼方式(UTF-8)2.編寫字元編碼過濾器 在過濾器中寫下一下程式碼:HttpServletRequest request = (HttpServletRequest)arg0;HttpServletResponse response = (HttpServ

java後臺傳遞json到前臺 中文亂碼解決方法

查了兩天 都說處理response 不過我搭建的框架裡沒有response(至少表面上沒有) 然後拼接了一個String作為json傳遞到前臺 但是遇到中文 前臺就顯示“?” 試過很多辦法 都不能解決 最後放棄了字串拼接 改為物件傳遞 結果成功了 controller對應方

C#對URL中的中文亂碼處理

res quest 類庫 處理 odin .dll 前言 中文亂碼 ring 前言:UTF-8中,一個漢字對應三個字節,GB2312中一個漢字占用兩個字節。 不論何種編碼,字母數字都不編碼,特殊符號編碼後占用一個字節。 1、直接在C#後臺編碼URL參數 引用類庫:Syste

Eclipse的properties文件中文亂碼解決方法

text content elf abd 問題 clas nbsp ips -o 轉自:http://jingyan.baidu.com/article/ed2a5d1f3381d709f6be17f8.html 打開Myeclipse,找到window這一欄,點

Datastage JDBC Connector 中文亂碼處理

default 中文亂碼 在Datastage中,通常處理中文字符編碼的時候是通過設置工程、JOB、stage三個級別的NLS但JDBC Connector stage這個組件並沒有NLS選項,而是通過 stage裏面的“Properties”選項卡裏面的“Session”-->“Charact

JAVA中文亂碼之解決方案

can tco con enc 字符 pos 好的 type nco 1.解決HTML頁面的中文問題:為了使HTML頁面很好的支持中文,在每個HTML頁面的<head>標簽內部增加(創建HTML頁面自帶) <head> <m

Codeblocks 中文亂碼解決方法

gif www 有效 file odi fault 輸入 打開文件 一個 1.修改源文件保存編碼 settings->Editor->gernal settings 右邊的Encoding group Box Use encoding when openin

MySQL中文亂碼處理_字符集轉換處理

MySQL 中文亂碼 字符集轉換-- 中文亂碼修復 -- 查看MySQL服務參數設置mysql> show variables like ‘%character%‘;+--------------------------+----------------------------------+| Vari

java 中文亂碼問題,請註意response.getWriter的順序

pos 順序 getwriter .get post div writer 問題 mage 反例: 正例: java 中文亂碼問題,請註意response.getWriter的順序

mysql防止中文亂碼方法

包括 英文 中文亂碼 適合 字符串 根據 color eat 程序 mysql字符集介紹 包括兩部分 字符集CHARACTER和校對規則COLLATION 字符集是用來定義mysql字符串存儲的方式 校對規則是定義比較

Java中文亂碼&特殊字符解決方案

tco 其它 exce 相同 blog 選擇 misc black 是什麽 Java中文亂碼&特殊字符解決方案 相信很多朋友遇到過Java的亂碼問題,最近我也在解決一個“使用文本生成圖片過程中中文以及特殊字符亂碼”的問題;花了我大量時間,Debug了sun.font