Java 與 UTF-8 編碼 (一)
使用 Java 的人應該都或多或少遇到過編碼問題吧,到底什麼時候要用什麼編碼,網頁要怎麼寫 charset,然後網頁的資訊傳遞的時候,接收的時候是不是還得要經過轉碼?最後進入 Database 的時候是不是還得要做一次編碼?真的會令人傻傻的分不清楚!
我之前寫過一篇關於 MySQL 安裝的筆記,我想要重新從 source code 安裝的一個很重要因素就是 UTF-8,因為中文的編碼是一件非常麻煩的事情,尤其 PHP + MySQL 還有很常被問到的 「許功蓋」問題。
因此我自己的經驗是可以 UTF-8 編碼的,就直接使用 UTF-8 編碼,這樣子是可以最輕鬆的。而現在的 Database 幾乎都是支援 Unicode 編碼了,例如:MS SQL Server、MySQL 等等。而除了 Database 之外,接下來就是程式語言以及網頁的部分。
網頁的部分又可以細分兩個部分,一個是存檔的時候是不是使用 UTF-8 編碼來存檔,另外一個是設定網頁的 charset。網頁的 charset 是由底下的 meta tag 來設定的:
meta http-equiv="Content-Type" content="text/html; charset=utf-8"
charset 是指定 browser 來瀏覽的時候該使用哪種語系來解析該頁面,這問題在 PHP 之類的語言比較少會遇到亂碼,但是對於 Java 就不一樣了。主要是 Java 底層就是使用 unicode 編碼,網頁程式如果是 JSP 的話還會先轉成 Servlet ( java 檔案),再 compile 成為 class 檔案。若是轉換的過程中 encoding 不一致,就可能變成亂碼了。這篇文章討論了網頁編碼以及進入 Database 編碼的問題,很值的一看。
我的經驗是一切都使用 UTF-8 編碼,包括存檔的時候以及 charset。舉個例子:
上面是很簡單的一個 form submit 例子,我分成兩種狀況 (BIG format 存檔以及 UTF-8 format 存檔)上面的檔案是以 BIG5 編碼方式去存檔 (光看內容是看不出來的,尤其都是英文的狀況)
1. 我把上面的內容以 html 的方式來呈現,並且 submit 資料給 Servlet。
Servlet 只是直接使用 request.getParameter("name") 的方式抓取資料並列印到頁面。結果是:(測試環境是 IE 6.0 以及 Tomcat 4.1.34)
至於處理該 JSP form 的 servlet 程式碼如下:
package com.esolution.test;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class EncodingTestServlet extends HttpServlet {
public void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doPost(req,resp);
}
public void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.setCharacterEncoding("utf-8");
String name = req.getParameter("name");
resp.setContentType("text/html;charset=utf-8");
PrintWriter out = resp.getWriter();
out.println(name+ "
");
}
}
上面會設定 HttpServletRequest 的 CharacterEncoding 為 UTF-8 以及 HttpServletResponse 的 content type。
檢視 HTML Source,結果也是「中文」沒錯。
2. 把上面的內容以 JSP 的方式存檔,並且同樣 submit 出去,會得到底下的結果:
不注意看,會覺得結果都一樣啊,也得到想要的中文結果了,可是如果仔細去看 HTML Source 卻會看到:
因為我上述的 form 是以 get 的方式傳遞的,仔細去看網址:
http://localhost:8080/WebTest/EncodingTestServlet?name=%26%2320013%3B%26%2325991%3B&Submit=Submit+Query
原來 name 是以 name=%26%2320013%3B%26%2325991%3B 的方式去傳遞的,而 %26 跟 %23 分別是 & 跟 # URL encode 的結果,而 20013 跟 25991 則是 「中」跟「文」的 code position。這篇文章有解釋到 HTML Character Reference,有興趣的人可以自己看一下。
%26%2320013%3B%26%2325991%3B 這樣的結果對於 browser 來說,還是可以呈現正確的結果,可是如果今天我們是要把這個資料存到 Database,那就會出問題了。我們總不希望存在 Database 裡面的是一些 browser 才看的懂的資料吧?
上面會出現這樣的結果,也就是常會讓大家覺得 Java 的編碼為什麼會有很多問題的感覺。同樣的東西,怎麼使用 HTML 跟 JSP 出來看到的結果雖然一樣,但是實際上的內容卻又有差別。這個主要就是 JSP 檔案並不是直接就呈現內容,還得要透過轉成 servlet (java file) 然後再 compile 成 class 檔案,再印出到 browser 上,所以只要有些地方編碼不一致,就可能出現錯誤了。
這篇先點出問題,下一篇再說怎麼解決這樣的狀況。明天還要一早起來坐車,今天不能太晚睡了。
沒有留言:
張貼留言