<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    backup2007

    導航

    <2025年5月>
    27282930123
    45678910
    11121314151617
    18192021222324
    25262728293031
    1234567

    統計

    公告

    @import url(http://m.tkk7.com/CuteSoft_Client/CuteEditor/Load.ashx?type=style&file=SyntaxHighlighter.css);@import url(/css/cuteeditor.css);


    常用鏈接

    留言簿(1)

    隨筆分類

    隨筆檔案

    文章分類

    文章檔案

    搜索

    最新評論

    閱讀排行榜

    評論排行榜

    2008年1月17日 #

    編碼問題3轉

    世界上的各地區都有本地的語言。地區差異直接導致了語言環境的差異。在開發一個國際化程序的過程中,處理語言問題就顯得很重要了。

      這是一個世界范圍內都存在的問題,所以,Java提供了世界性的解決方法。本文描述的方法是用于處理中文的,但是,推而廣之,對于處理世界上其它國家和地區的語言同樣適用。

      漢字是雙字節的。所謂雙字節是指一個雙字要占用兩個BYTE的位置(即16位),分別稱為高位和低位。中國規定的漢字編碼為GB2312,這是 強制性的,目前幾乎所有的能處理中文的應用程序都支持GB2312。GB2312包括了一二級漢字和9區符號,高位從0xa1到0xfe,低位也是從 0xa1到0xfe,其中,漢字的編碼范圍為0xb0a1到0xf7fe。

      另外有一種編碼,叫做GBK,但這是一份規范,不是強制的。GBK提供了20902個漢字,它兼容GB2312,編碼范圍為0x8140到0xfefe。GBK中的所有字符都可以一一映射到Unicode 2.0。

      在不久的將來,中國會頒布另一種標準:GB18030-2000(GBK2K)。它收錄了藏、蒙等少數民族的字型,從根本上解決了字位不足的問 題。注意:它不再是定長的。其二字節部份與GBK兼容,四字節部分是擴充的字符、字形。它的首字節和第三字節從0x81到0xfe,二字節和第四字節從 0x30到0x39。

      本文不打算介紹Unicode,有興趣的可以瀏覽“http://www.unicode.org/”查看更多的信息。Unicode有一個特 性:它包括了世界上所有的字符字形。所以,各個地區的語言都可以建立與Unicode的映射關系,而Java正是利用了這一點以達到異種語言之間的轉換。

      在JDK中,與中文相關的編碼有:

      表1 JDK中與中文相關的編碼列表
    編碼名稱 說明
    ASCII 7位,與ascii7相同
    ISO8859-1 8-位,與 8859_1,ISO-8859-1,ISO_8859-1,latin1...等相同
    GB2312-80 16位,與gb2312,gb2312-1980,EUC_CN,euccn,1381,Cp1381, 1383, Cp1383, ISO2022CN,ISO2022CN_GB...等相同
    GBK 與MS936相同,注意:區分大小寫
    UTF8 與UTF-8相同
    GB18030 與cp1392、1392相同,目前支持的JDK很少

      在實際編程時,接觸得比較多的是GB2312(GBK)和ISO8859-1。

      為什么會有“?”號

      上文說過,異種語言之間的轉換是通過Unicode來完成的。假設有兩種不同的語言A和B,轉換的步驟為:先把A轉化為Unicode,再把Unicode轉化為B。

      舉例說明。有GB2312中有一個漢字“李”,其編碼為“C0EE”,欲轉化為ISO8859-1編碼。步驟為:先把“李”字轉化為 Unicode,得到“674E”,再把“674E”轉化為ISO8859-1字符。當然,這個映射不會成功,因為ISO8859-1中根本就沒有與 “674E”對應的字符。

      當映射不成功時,問題就發生了!當從某語言向Unicode轉化時,如果在某語言中沒有該字符,得到的將是Unicode的代碼“" uffffd”(“"u”表示是Unicode編碼,)。而從Unicode向某語言轉化時,如果某語言沒有對應的字符,則得到的是“0x3f” (“?”)。這就是“?”的由來。

      例如:把字符流buf =“0x80 0x40 0xb0 0xa1”進行new String(buf, "gb2312")操作,得到的結果是“"ufffd"u554a”,再println出來,得到的結果將是“?啊”,因為“0x80 0x40”是GBK中的字符,在GB2312中沒有。

      再如,把字符串String=""u00d6"u00ec"u00e9"u0046"u00bb"u00f9"進行new String (buf.getBytes("GBK"))操作,得到的結果是“3fa8aca8a6463fa8b4”,其中,“"u00d6”在“GBK”中沒有對 應的字符,得到“3f”,“"u00ec”對應著“a8ac”,“"u00e9”對應著“a8a6”,“0046”對應著“46”(因為這是ASCII字 符),“"u00bb”沒找到,得到“3f”,最后,“"u00f9”對應著“a8b4”。把這個字符串println一下,得到的結果是“?ìéF? ù”。看到沒?這里并不全是問號,因為GBK與Unicode映射的內容中除了漢字外還有字符,本例就是最好的明證。

      所以,在漢字轉碼時,如果發生錯亂,得到的不一定都是問號噢!不過,錯了終究是錯了,50步和100步并沒有質的差別。

      或者會問:如果源字符集中有,而Unicode中沒有,結果會如何?回答是不知道。因為我手頭沒有能做這個測試的源字符集。但有一點是肯定的,那就是源字符集不夠規范。在Java中,如果發生這種情況,是會拋出異常的。

    什么是UTF

      UTF,是Unicode Text Format的縮寫,意為Unicode文本格式。對于UTF,是這樣定義的:

      (1)如果Unicode的16位字符的頭9位是0,則用一個字節表示,這個字節的首位是“0”,剩下的7位與原字符中的后7位相同,如“" u0034”(0000 0000 0011 0100),用“34” (0011 0100)表示;(與源Unicode字符是相同的);

      (2)如果Unicode的16位字符的頭5位是0,則用2個字節表示,首字節是“110”開頭,后面的5位與源字符中除去頭5個零后的最高5 位相同;第二個字節以“10”開頭,后面的6位與源字符中的低6位相同。如“"u025d”(0000 0010 0101 1101),轉化后為“c99d”(1100 1001 1001 1101);

      (3)如果不符合上述兩個規則,則用三個字節表示。第一個字節以“1110”開頭,后四位為源字符的高四位;第二個字節以“10”開頭,后六位 為源字符中間的六位;第三個字節以“10”開頭,后六位為源字符的低六位;如“"u9da7”(1001 1101 1010 0111),轉化為“e9b6a7”(1110 1001 1011 0110 1010 0111);

      可以這么描述JAVA程序中Unicode與UTF的關系,雖然不絕對:字符串在內存中運行時,表現為Unicode代碼,而當要保存到文件或其它介質中去時,用的是UTF。這個轉化過程是由writeUTF和readUTF來完成的。

      好了,基礎性的論述差不多了,下面進入正題。

      先把這個問題想成是一個黑匣子。先看黑匣子的一級表示:

    input(charsetA)->process(Unicode)->output(charsetB)

      簡單,這就是一個IPO模型,即輸入、處理和輸出。同樣的內容要經過“從charsetA到unicode再到charsetB”的轉化。

      再看二級表示:

    SourceFile(jsp,java)->class->output

      在這個圖中,可以看出,輸入的是jsp和java源文件,在處理過程中,以Class文件為載體,然后輸出。再細化到三級表示:

    jsp->temp file->class->browser,os console,db

    app,servlet->class->browser,os console,db

      這個圖就更明白了。Jsp文件先生成中間的Java文件,再生成Class。而Servlet和普通App則直接編譯生成Class。然后,從Class再輸出到瀏覽器、控制臺或數據庫等。

      JSP:從源文件到Class的過程

      Jsp的源文件是以“.jsp”結尾的文本文件。在本節中,將闡述JSP文件的解釋和編譯過程,并跟蹤其中的中文變化。

      1、JSP/Servlet引擎提供的JSP轉換工具(jspc)搜索JSP文件中用<%@ page contentType ="text/html; charset=<Jsp-charset>"%>中指定的charset。如果在JSP文件中未指定<Jsp- charset>,則取JVM中的默認設置file.encoding,一般情況下,這個值是ISO8859-1;

      2、jspc用相當于“javac –encoding <Jsp-charset>”的命令解釋JSP文件中出現的所有字符,包括中文字符和ASCII字符,然后把這些字符轉換成Unicode字 符,再轉化成UTF格式,存為JAVA文件。ASCII碼字符轉化為Unicode字符時只是簡單地在前面加“00”,如“A”,轉化為“"u0041” (不需要理由,Unicode的碼表就是這么編的)。然后,經過到UTF的轉換,又變回“41”了!這也就是可以使用普通文本編輯器查看由JSP生成的 JAVA文件的原因;

      3、引擎用相當于“javac –encoding UNICODE”的命令,把JAVA文件編譯成CLASS文件;

      先看一下這些過程中中文字符的轉換情況。有如下源代碼:

    <%@ page contentType="text/html; charset=gb2312"%>
    <html><body>
    <%
    String a="中文";
    out.println(a);
    %>
    </body></html>

      這段代碼是在UltraEdit for Windows上編寫的。保存后,“中文”兩個字的16進制編碼為“D6 D0 CE C4”(GB2312編碼)。經查表,“中文”兩字的Unicode編碼為“"u4E2D"u6587”,用 UTF表示就是“E4 B8 AD E6 96 87”。打開引擎生成的由JSP文件轉變而成的JAVA文件,發現其中的“中文”兩個字確實被“E4 B8 AD E6 96 87”替代了,再查看由JAVA文件編譯生成的CLASS文件,發現結果與JAVA文件中的完全一樣。

      再看JSP中指定的CharSet為ISO-8859-1的情況。

    <%@ page contentType="text/html; charset=ISO-8859-1"%>
    <html><body>
    <%
    String a="中文";
    out.println(a);
    %>
    </body></html>

      同樣,該文件是用UltraEdit編寫的,“中文”這兩個字也是存為GB2312編碼“D6 D0 CE C4”。先模擬一下生成的JAVA文件和CLASS文件的過程:jspc用ISO-8859-1來解釋“中文”,并把它映射到Unicode。由于ISO -8859-1是8位的,且是拉丁語系,其映射規則就是在每個字節前加“00”,所以,映射后的Unicode編碼應為“"u00D6"u00D0" u00CE"u00C4”,轉化成UTF后應該是“C3 96 C3 90 C3 8E C3 84”。好,打開文件看一下,JAVA文件和CLASS文件中,“中文”果然都表示為“C3 96 C3 90 C3 8E C3 84”。

      如果上述代碼中不指定<Jsp-charset>,即把第一行寫成“<%@ page contentType="text/html" %>”,JSPC會使用file.encoding的設置來解釋JSP文件。在RedHat 6.2上,其處理結果與指定為ISO-8859-1是完全相同的。

      到現在為止,已經解釋了從JSP文件到CLASS文件的轉變過程中中文字符的映射過程。一句話:從“JspCharSet到Unicode再到UTF”。下表總結了這個過程:

      表2 “中文”從JSP到CLASS的轉化過程
    Jsp-CharSet JSP文件中 JAVA文件中 CLASS文件中
    GB2312 D6 D0 CE C4(GB2312) 從"u4E2D"u6587(Unicode)到E4 B8 AD E6 96 87 (UTF) E4 B8 AD E6 96 87 (UTF)
    ISO-8859-1 D6 D0 CE C4
    (GB2312)
    從"u00D6"u00D0"u00CE"u00C4 (Unicode)到C3 96 C3 90 C3 8E C3 84 (UTF) C3 96 C3 90 C3 8E C3 84 (UTF)
    無(默認=file.encoding) 同ISO-8859-1 同ISO-8859-1 同ISO-8859-1

    下節先討論Servlet從JAVA文件到CLASS文件的轉化過程,然后再解釋從CLASS文件如何輸出到客戶端。之所以這樣安排,是因為JSP和Servlet在輸出時處理方法是一樣的。

      Servlet:從源文件到Class的過程

      Servlet源文件是以“.java”結尾的文本文件。本節將討論Servlet的編譯過程并跟蹤其中的中文變化。

      用“javac”編譯Servlet源文件。javac可以帶“-encoding <Compile-charset>”參數,意思是“用< Compile-charset >中指定的編碼來解釋Serlvet源文件”。

      源文件在編譯時,用<Compile-charset>來解釋所有字符,包括中文字符和ASCII字符。然后把字符常量轉變成Unicode字符,最后,把Unicode轉變成UTF。

      在Servlet中,還有一個地方設置輸出流的CharSet。通常在輸出結果前,調用HttpServletResponse的 setContentType方法來達到與在JSP中設置<Jsp-charset>一樣的效果,稱之為<Servlet- charset>。

      注意,文中一共提到了三個變量:<Jsp-charset>、<Compile-charset>和< Servlet-charset>。其中,JSP文件只與<Jsp-charset>有關,而<Compile- charset>和<Servlet-charset>只與Servlet有關。

      看下例:

    import javax.servlet.*;

    import javax.servlet.http.*;

    class testServlet extends HttpServlet
    {
    public void doGet(HttpServletRequest req,HttpServletResponse resp)
    throws ServletException,java.io.IOException
    {
    resp.setContentType("text/html; charset=GB2312");
    java.io.PrintWriter out=resp.getWriter();
    out.println("<html>");
    out.println("#中文#");
    out.println("</html>");
    }
    }

      該文件也是用UltraEdit for Windows編寫的,其中的“中文”兩個字保存為“D6 D0 CE C4”(GB2312編碼)。

      開始編譯。下表是<Compile-charset>不同時,CLASS文件中“中文”兩字的十六進制碼。在編譯過程中,< Servlet-charset>不起任何作用。<Servlet-charset>只對CLASS文件的輸出產生影響,實際上是 <Servlet-charset>和<Compile-charset>一起,達到與JSP文件中的<Jsp- charset>相同的效果,因為<Jsp-charset>對編譯和CLASS文件的輸出都會產生影響。

      表3 “中文”從Servlet源文件到Class的轉變過程
    Compile-charset Servlet源文件中 Class文件中 等效的Unicode碼
    GB2312 D6 D0 CE C4
    (GB2312)
    E4 B8 AD E6 96 87 (UTF) "u4E2D"u6587 (在Unicode中=“中文”)
    ISO-8859-1 D6 D0 CE C4
    (GB2312)
    C3 96 C3 90 C3 8E C3 84 (UTF) "u00D6 "u00D0 "u00CE "u00C4 (在D6 D0 CE C4前面各加了一個00)
    無(默認) D6 D0 CE C4 (GB2312) 同ISO-8859-1 同ISO-8859-1

    普通Java程序的編譯過程與Servlet完全一樣。

    CLASS文件中的中文表示法是不是昭然若揭了?OK,接下來看看CLASS又是怎樣輸出中文的呢?

    Class:輸出字符串

    上文說過,字符串在內存中表現為Unicode編碼。至于這種Unicode編碼表示了什么,那要看它是從哪種字符集映射過來的,也就是說要看它的祖先。這好比在托運行李時,外觀都是紙箱子,里面裝了什么就要看寄郵件的人實際郵了什么東西。

    看看上面的例子,如果給一串Unicode編碼“00D6 00D0 00CE 00C4”,如果不作轉換,直接用Unicode碼表來對照它時,是四個字符(而且是特殊字符);假如把它與“ISO8859-1”進行映射,則直接去掉 前面的“00”即可得到“D6 D0 CE C4”,這是ASCII碼表中的四個字符;而假如把它當作GB2312來進行映射,得到的結果很可能是一大堆亂碼,因為在GB2312中有可能沒有(也有 可能有)字符與00D6等字符對應(如果對應不上,將得到0x3f,也就是問號,如果對應上了,由于00D6等字符太靠前,估計也是一些特殊符號,真正的 漢字在Unicode中的編碼從4E00開始)。

    各位看到了,同樣的Unicode字符,可以解釋成不同的樣子。當然,這其中有一種是我們期望的結果。以上例而論,“D6 D0 CE C4”應該是我們所想要的,當把“D6 D0 CE C4”輸出到IE中時,用“簡體中文”方式查看,就能看到清楚的“中文”兩個字了。(當然了,如果你一定要用“西歐字符”來看,那也沒辦法,你將得不到任何有何時何地的東西)為什么呢?因為“00D6 00D0 00CE 00C4”本來就是由ISO8859-1轉化過去的。
      給出如下結論:

    在Class輸出字符串前,會將Unicode的字符串按照某一種內碼重新生成字節流,然后把字節流輸入,相當于進行了一步“String.getBytes(???)”操作。???代表某一種字符集。

    如果是Servlet,那么,這種內碼就是在HttpServletResponse.setContentType()方法中指定的內碼,也就是上文定義的<Servlet-charset>。

    如果是JSP,那么,這種內碼就是在<%@ page contentType=""%>中指定的內碼,也就是上文定義的<Jsp-charset>。

    如果是Java程序,那么,這種內碼就是file.encoding中指定的內碼,默認為ISO8859-1。

    當輸出對象是瀏覽器時

    以流行的瀏覽器IE為例。IE支持多種內碼。假如IE接收到了一個字節流“D6 D0 CE C4”,你可以嘗試用各種內碼去查看。你會發現用“簡體中文”時能得到正確的結果。因為“D6 D0 CE C4”本來就是簡體中文中“中文”兩個字的編碼。

    OK,完整地看一遍。

    JSP:源文件為GB2312格式的文本文件,且JSP源文件中有“中文”這兩個漢字

    如果指定了<Jsp-charset>為GB2312,轉化過程如下表。

    表4 Jsp-charset = GB2312時的變化過程

    序號 步驟說明 結果
    1 編寫JSP源文件,且存為GB2312格式 D6 D0 CE C4
    (D6D0=中 CEC4=文)
    2 jspc把JSP源文件轉化為臨時JAVA文件,并把字符串按照GB2312映射到Unicode,并用UTF格式寫入JAVA文件中 E4 B8 AD E6 96 87
    3 把臨時JAVA文件編譯成CLASS文件 E4 B8 AD E6 96 87
    4 運行時,先從CLASS文件中用readUTF讀出字符串,在內存中的是Unicode編碼 4E 2D 65 87(在Unicode中4E2D=中 6587=文)
    5 根據Jsp-charset=GB2312把Unicode轉化為字節流 D6 D0 CE C4
    6 把字節流輸出到IE中,并設置IE的編碼為GB2312(作者按:這個信息隱藏在HTTP頭中) D6 D0 CE C4
    7 IE用“簡體中文”查看結果 “中文”(正確顯示)

    如果指定了<Jsp-charset>為ISO8859-1,轉化過程如下表。

    表5 Jsp-charset = ISO8859-1時的變化過程

    序號 步驟說明 結果
    1 編寫JSP源文件,且存為GB2312格式 D6 D0 CE C4
    (D6D0=中 CEC4=文)
    2 jspc把JSP源文件轉化為臨時JAVA文件,并把字符串按照ISO8859-1映射到Unicode,并用UTF格式寫入JAVA文件中 C3 96 C3 90 C3 8E C3 84
    3 把臨時JAVA文件編譯成CLASS文件 C3 96 C3 90 C3 8E C3 84
    4 運行時,先從CLASS文件中用readUTF讀出字符串,在內存中的是Unicode編碼 00 D6 00 D0 00 CE 00 C4
    (啥都不是!!!)
    5 根據Jsp-charset=ISO8859-1把Unicode轉化為字節流 D6 D0 CE C4
    6 把字節流輸出到IE中,并設置IE的編碼為ISO8859-1(作者按:這個信息隱藏在HTTP頭中) D6 D0 CE C4
    7 IE用“西歐字符”查看結果 亂碼,其實是四個ASCII字符,但由于大于128,所以顯示出來的怪模怪樣
    8 改變IE的頁面編碼為“簡體中文” “中文”(正確顯示)

    奇怪了!為什么把<Jsp-charset>設成GB2312和ISO8859-1是一個樣的,都能正確顯示?因為表4表5中的第2步和第5步互逆,是相互“抵消”的。只不過當指定為ISO8859-1時,要增加第8步操作,殊為不便。

    再看看不指定<Jsp-charset> 時的情況。

    表6 未指定Jsp-charset 時的變化過程

    序號 步驟說明 結果
    1 編寫JSP源文件,且存為GB2312格式 D6 D0 CE C4
    (D6D0=中 CEC4=文)
    2 jspc把JSP源文件轉化為臨時JAVA文件,并把字符串按照ISO8859-1映射到Unicode,并用UTF格式寫入JAVA文件中 C3 96 C3 90 C3 8E C3 84
    3 把臨時JAVA文件編譯成CLASS文件 C3 96 C3 90 C3 8E C3 84
    4 運行時,先從CLASS文件中用readUTF讀出字符串,在內存中的是Unicode編碼 00 D6 00 D0 00 CE 00 C4
    5 根據Jsp-charset=ISO8859-1把Unicode轉化為字節流 D6 D0 CE C4
    6 把字節流輸出到IE中 D6 D0 CE C4
    7 IE用發出請求時的頁面的編碼查看結果 視情況而定。如果是簡體中文,則能正確顯示,否則,需執行表5中的第8步

    Servlet:源文件為JAVA文件,格式是GB2312,源文件中含有“中文”這兩個漢字

    如果<Compile-charset>=GB2312,<Servlet-charset>=GB2312

    表7 Compile-charset=Servlet-charset=GB2312 時的變化過程

    序號 步驟說明 結果
    1 編寫Servlet源文件,且存為GB2312格式 D6 D0 CE C4
    (D6D0=中 CEC4=文)
    2 用javac –encoding GB2312把JAVA源文件編譯成CLASS文件 E4 B8 AD E6 96 87 (UTF)
    3 運行時,先從CLASS文件中用readUTF讀出字符串,在內存中的是Unicode編碼 4E 2D 65 87 (Unicode)
    4 根據Servlet-charset=GB2312把Unicode轉化為字節流 D6 D0 CE C4 (GB2312)
    5 把字節流輸出到IE中并設置IE的編碼屬性為Servlet-charset=GB2312 D6 D0 CE C4 (GB2312)
    6 IE用“簡體中文”查看結果 “中文”(正確顯示)

    如果<Compile-charset>=ISO8859-1,<Servlet-charset>=ISO8859-1

    表8 Compile-charset=Servlet-charset=ISO8859-1時的變化過程

    序號 步驟說明 結果
    1 編寫Servlet源文件,且存為GB2312格式 D6 D0 CE C4
    (D6D0=中 CEC4=文)
    2 用javac –encoding ISO8859-1把JAVA源文件編譯成CLASS文件 C3 96 C3 90 C3 8E C3 84 (UTF)
    3 運行時,先從CLASS文件中用readUTF讀出字符串,在內存中的是Unicode編碼 00 D6 00 D0 00 CE 00 C4
    4 根據Servlet-charset=ISO8859-1把Unicode轉化為字節流 D6 D0 CE C4
    5 把字節流輸出到IE中并設置IE的編碼屬性為Servlet-charset=ISO8859-1 D6 D0 CE C4 (GB2312)
    6 IE用“西歐字符”查看結果 亂碼(原因同表5)
    7 改變IE的頁面編碼為“簡體中文” “中文”(正確顯示)

    如果不指定Compile-charset或Servlet-charset,其默認值均為ISO8859-1。

    當Compile-charset=Servlet-charset時,第2步和第4步能互逆,“抵消”,顯示結果均能正確。讀者可試著寫一下Compile-charset<>Servlet-charset時的情況,肯定是不正確的。

    當輸出對象是數據庫時

    輸出到數據庫時,原理與輸出到瀏覽器也是一樣的。本節只是Servlet為例,JSP的情況請讀者自行推導。

    假設有一個Servlet,它能接收來自客戶端(IE,簡體中文)的漢字字符串,然后把它寫入到內碼為ISO8859-1的數據庫中,然后再從數據庫中取出這個字符串,顯示到客戶端。

    表9 輸出對象是數據庫時的變化過程(1)

    序號 步驟說明 結果
    1 在IE中輸入“中文” D6 D0 CE C4 IE
    2 IE把字符串轉變成UTF,并送入傳輸流中 E4 B8 AD E6 96 87
    3 Servlet接收到輸入流,用readUTF讀取 4E 2D 65 87(unicode) Servlet
    4 編程者在Servlet中必須把字符串根據GB2312還原為字節流 D6 D0 CE C4
    5 編程者根據數據庫內碼ISO8859-1生成新的字符串 00 D6 00 D0 00 CE 00 C4
    6 把新生成的字符串提交給JDBC 00 D6 00 D0 00 CE 00 C4
    7 JDBC檢測到數據庫內碼為ISO8859-1 00 D6 00 D0 00 CE 00 C4 JDBC
    8 JDBC把接收到的字符串按照ISO8859-1生成字節流 D6 D0 CE C4
    9 JDBC把字節流寫入數據庫中 D6 D0 CE C4
    10 完成數據存儲工作 D6 D0 CE C4 數據庫
    以下是從數據庫中取出數的過程
    11 JDBC從數據庫中取出字節流 D6 D0 CE C4 JDBC
    12 JDBC按照數據庫的字符集ISO8859-1生成字符串,并提交給Servlet 00 D6 00 D0 00 CE 00 C4 (Unicode)  
    13 Servlet獲得字符串 00 D6 00 D0 00 CE 00 C4 (Unicode) Servlet
    14 編程者必須根據數據庫的內碼ISO8859-1還原成原始字節流 D6 D0 CE C4  
    15 編程者必須根據客戶端字符集GB2312生成新的字符串 4E 2D 65 87
    (Unicode)
     
    Servlet準備把字符串輸出到客戶端
    16 Servlet根據<Servlet-charset>生成字節流 D6D0 CE C4 Servlet
    17 Servlet把字節流輸出到IE中,如果已指定<Servlet-charset>,還會設置IE的編碼為<Servlet-charset> D6 D0 CE C4
    18 IE根據指定的編碼或默認編碼查看結果 “中文”(正確顯示) IE

    解釋一下,表中第4第5步和第15第16步是用紅色標記的,表示要由編碼 者來作轉換。第4、5兩步其實就是一句話:“new String(source.getBytes("GB2312"), "ISO8859-1")”。第15、16兩步也是一句話:“new String(source.getBytes("ISO8859-1"), "GB2312")”。親愛的讀者,你在這樣編寫代碼時是否意識到了其中的每一個細節呢?

    至于客戶端內碼和數據庫內碼為其它值時的流程,和輸出對象是系統控制臺時的流程,請讀者自己想吧。明白了上述流程的原理,相信你可以輕松地寫出來。

    行文至此,已可告一段落了。終點又回到了起點,對于編程者而言,幾乎是什么影響都沒有。

    因為我們早就被告之要這么做了。

    以下給出一個結論,作為結尾。

    1、 在Jsp文件中,要指定contentType,其中,charset的值要與客戶端瀏覽器所用的字符集一樣;對于其中的字符串常量,不需做任何內碼轉 換;對于字符串變量,要求能根據ContentType中指定的字符集還原成客戶端能識別的字節流,簡單地說,就是“字符串變量是基于<Jsp- charset>字符集的”;

    2、 在Servlet中,必須用HttpServletResponse.setContentType()設置charset,且設置成與客戶端內碼一致; 對于其中的字符串常量,需要在Javac編譯時指定encoding,這個encoding必須與編寫源文件的平臺的字符集一樣,一般說來都是 GB2312或GBK;對于字符串變量,與JSP一樣,必須“是基于<Servlet-charset>字符集的”。

    posted @ 2008-01-17 14:34 backup2007 閱讀(517) | 評論 (0)編輯 收藏

    編碼問題2轉

    Jsp頁面使用URL編碼傳遞中文參數的情況下,在參數的解析過程中會出現亂碼。由于 java在設計的時候考慮到了國際化的問題,在java源程序編譯成字節碼的時候默認使用的是UTF-8編碼。而在web運用上,由于不同的瀏覽器向服務 器發送的信息采用的編碼方式不同,在由像tomcat之類的服務器解碼的時候會由于編碼方式的不同而產生亂碼,這是一個會困擾jsp初學者很久的問題。以 前在使用struts的時候不需要處理這些問題,前些天在做一個簡單的jsp頁面的時候碰到這個問題。經過半天的摸索,基本解決了該問題。
    例子中a.jsp頁面通過URL編碼的方式傳遞中文參數,在b.jsp中對該參數進行解析。
    a.jsp源代碼
    <%@ page contentType="text/html; charset=gb2312" language="java" import="java.sql.*" errorPage="" %>
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=gb2312" />
    <title>無標題文檔</title>
    </head>
     
    <body>
    <% 
           String str_test = "華工";
    %>
    <form method=post action="b.jsp?test=<%=java.net.URLEncoder.encode(str_test) %>"> 
             <input type="submit" value="Submit" name="提交">  
     </form>
     
    </body>
    </html>
     
    b.jsp源代碼
    <%@ page contentType="text/html; charset=gb2312" language="java" import="java.sql.*" errorPage="" %>
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=gb2312" />
    <title>無標題文檔</title>
    </head>
     
    <body>
     
    <%
           String str = new String(request.getParameter("test").getBytes("ISO8859_1"));
    %> 
     <BR>
     <%=str %>
    </body>
    </html>
    說明:在使用了java.net.URLEncoder.encode 編碼后,頁面獲取參數request.getParameter后需要使用ISO8859_1編碼轉換。此外,在jsp的字符集聲明中把charset=UTF-8也沒有問題

    posted @ 2008-01-17 14:30 backup2007 閱讀(218) | 評論 (0)編輯 收藏

    編碼問題1 轉

         摘要: HTML:     ……     //實際上這里的charset=utf-8 也是可以的,因為在中文平臺下     //用了GB2312     JS:     我用了兩個方法提交:GET 和 POST。 ...  閱讀全文

    posted @ 2008-01-17 14:29 backup2007 閱讀(550) | 評論 (0)編輯 收藏

    2007年12月24日 #

    vim 常用命令 轉

    1、vim顏色太暗,默認的尤其是注釋顏色太暗,根本看不清,可通過下述方式設置
    :colorscheme evening

    2、vim以16進制方式編輯文件:
    :%!xxd

    3、用vim格式化代碼
    從別的編輯器里粘貼到vim里的代碼經常由于不正常的縮進變得格式混亂,有如下兩種方式:
    格式化全文: gg=G
    自動縮進當前行: ==

    4、vim退出后在
    屏幕上保留被編輯文件的內容:
    :set t_ti= t_te=

    5、多文件編輯
    打開多個文件:vim a.c b.c b.c
    切換到下一文件:n
    切換到另一文件:e <文件名如b.c>
    返回上一文件: e#

    橫向分屏:split (不加參數為分屏當前文件,加文件名為以分屏方式打開另一文件)
    豎向分屏:vsplit,與split不同之處在于豎向分屏
    分屏后切換:ctrl+兩次按w

    6、刪除內容到緩沖區
    x為刪除光標當前字符,而X則刪除光標前字符;
    dd為刪除當前行;
    nx,nX,ndd則表明刪除的數目;

    7、拷貝內容到緩沖區
    yy,為拷貝當前行到緩沖區;
    yw,為拷貝單個詞到緩沖區;
    nyy,nyw則表明拷貝的數目;

    8、移動到某一行:
    : n,n為行號

    nG,n為行號

    9、visual編輯
    三種進入方式:
    v ---- 以字符為單位進行選擇
    V ---- 以行為單位進行選擇
    ctrl+v ---- 以列塊方式進行選擇
    ctrl+c ---- 退出visual編輯方式

    進入后對選擇進行的操作有:
    d --- 刪除
    y --- 復制
    > --- 右移4格
    < --- 左移4格
    ~ --- 大小寫切換
    U --- 變成大寫
    u --- 變成小寫

    posted @ 2007-12-24 18:33 backup2007 閱讀(729) | 評論 (0)編輯 收藏

    quote : installnation of eclipse for java

    1. 下載文件
    JDK    jdk-1_5_0_06-linux-i586-rpm.bin  http://java.sun.com
    eclipse    eclipse-SDK-3.1.2-linux-gtk.tar.gz  http://www.eclipse.org
    CDT    org.eclipse.cdt-3.0.2-linux.x86.tar.gz  http://www.eclipse.org/cdt

    2. 安裝JDK

    chmod +x jdk-1_5_0_06-linux-i586-rpm.bin
    ./jdk-1_5_0_06-linux-i586-rpm.bin

    設置環境變量,編輯/etc/profile,在下面加入

    export JAVA_HOME=/usr/java/jdk1.5.0_06
    export PATH=$JAVA_HOME/bin:$PATH
    CLASSPATH=.:/usr/java/jdk1.5.0_06/lib/tools.jar:$CLASSPATH
    export CLASSPATH

    3. 安裝eclipse

    tar -zxvf eclipse-SDK-3.1.2-linux-gtk.tar.gz

    再移動到想要的目錄中,這里為/opt
    編寫一個執行腳本,內容如下:

    #eclipse
    #
    export JAVA_HOME=/usr/java/jdk1.5.0_06
    export CLASSPATH=/usr/java/jdk1.5.0_06/lib
    /opt/eclipse/eclipse -vm /usr/java/jdk1.5.0_06/bin/java -data ~/workspace &

    cp eclipse.sh /usr/local/bin
    chmod 755 /usr/local/bin/eclipse.sh

    將eclipse.sh 添加到桌面。桌面上按下鼠標右鍵,在彈出菜單中選擇“創建啟動器”,在“名稱”中輸入Eclipse、“命令”中填 /usr/local/bin/eclipse.sh,按“確定”,桌面上就有eclipse的快捷方式了,以后可以直接雙擊這個圖標啟動 Eclipse。

    4. 安裝CDT

    tar -zxvf org.eclipse.cdt-3.0.2-linux.x86.tar.gz

    將相映目錄中的文件cp到eclipse目錄中





    ---------------------

    先要在linux下安裝好jre,我的jre的安裝目錄是/usr/java/jre1.5

    把下載的文件解壓即可:

    #tar -zxvf eclipse-SDK-3.2-linux-gtk.tar.gz(可以加上絕對路徑)

    3 為讓每個用戶都可以執行Eclipse,編寫Eclipse.sh腳本:

    #!/bin/bash

    #

    #exe eclipse3.2

    #

    /usr/eclipse/eclipse -vm /usr/java/jre1.5/bin/java -data ~/workspace &

    # -vm 參數用以指定使用哪一個 jvm 來執行Eclipse

    # -date參數用以指定Eclipse的數據目錄。在此指定其存在用戶根目錄(~)下的workspace目錄中

    eclipse.sh 復制到/usr/local/bin中,并為它加上權限755;現在執行 eclipse.sh 即可啟動 Eclipse

    4桌面上建立快捷方式:

    在桌面上按下鼠標右鍵,在彈出菜單中選擇“新增啟動”,之后分別在“名稱”中輸入Eclipse3.2,“命令”中填 /usr/local/bin/eclipse.sh,然后再為它隨便找個喜歡的圖標(我用的是/opt/eclipse/icon.xpm;再后按“確定”,桌面上就有eclipse的快捷方式了,以后可以直接雙擊這個圖標啟動Eclipse

    posted @ 2007-12-24 17:21 backup2007 閱讀(311) | 評論 (0)編輯 收藏

    轉 eclipse3.3 + minGW for c/c++ development

    本設置的主要目的是在最新版的eclipse3.3(Europa)上開發標準C/C++程序,而不去使用VC++。

    因為CDT只提供了開發C/C++項目的IDE,所以我們需要安裝MinGW(即 Minimalist GNU For Windows。它是一些頭文件和端口庫的集合,該集合允許人們在沒有第三方動態鏈接庫的情況下使用 GCC(GNU Compiler C)產生 Windows32 程序。)和MSYS(Minimal GNU(POSIX)system on Windows,是一個小型的GNU環境,包括基本的bash,make等等。是Windows下最優秀的GNU環境。):
    下載Automated MinGW Installer:MinGW-5.1.3.exe(注意這只是個在線安裝程序),執行MinGW-5.1.3.exe;
    在choose package向導頁,選擇Current項;
    在choose components向導頁,選中MinGW base tools和g++ compiler項;
    在choose install location向導頁,設置安裝目錄,為說明方便,這里假設路徑為d:\MinGW;
    等待MinGW在線安裝完成。
    接下來,在下載MinGW的同一頁面,我們下載MSYS (Minimal System):Current Release: msys-1.0.10,執行MSYS-1.0.10.exe;
    在安裝MSYS過程中,假定我們安裝路徑為D:\msys;
    在安裝MSYS過程中,會出現控制臺界面(類DOS窗口)的三個詢問,分別鍵入y、y、D:/MinGW(MinGW安裝路徑)即可。
    安裝好MinGW和MYYS后,需要配置一下系統的環境變量,右鍵點擊“我的電腦”->屬性->高級->環境變量,在系統變量中進行如下操作:
    編輯PATH變量,在開頭處加入D:\MinGW\bin;D:\msys\1.0\bin;
    添加LIBRARY_PATH變量,值為D:\MinGW\lib
    添加C_INCLUDE_PATH變量,值為D:\MinGW\include
    添加CPLUS_INCLUDE_PATH變量,值為D:\MinGW\include\c++\3.4.2;D:\MinGW\include\c++\3.4.2\mingw32;D:\MinGW\include\c++\3.4.2\backward;D:\MinGW\include
    打開系統開始菜單->附件->命令提示符,在里面輸入make –version或gcc –version并回車,如果出現版本信息,則配置成功。
    如果你的系統上沒有安裝jre,去下載最新版的jre5.0,并進行安裝。
    接下來這步,我們先進入到http://www.eclipse.org/downloads/頁面,最好直接下載Eclipse IDE for C/C++ Developers - Windows (62 MB) 這個版本,基本上下載完后就可以正常使用。

    如果你已經有了eclipse3.3但需要單獨安裝CDT4的話,請參見這里CDT Europa Releases Update Site,里面說的很清楚,可以在eclipse的help->Software Updates -> Find and Install -> Search for new Features to Install中,加入一個site http://download.eclipse.org/tools/cdt/releases/europa升級即可。

    值得注意的是,不要直接下載cdt-master-4.0.0.zip,并且解壓縮后覆蓋到eclipse目錄下!,否則雖然可以調出CDT界面,但編譯和執行會有問題。

    最后,我們啟動eclipse并進行一個測試,創建一個C++ Project,選擇Executable->Hello World C++ Project,toolchain選擇MinGW GCC。創建后build它即可。

    posted @ 2007-12-24 11:51 backup2007 閱讀(1290) | 評論 (0)編輯 收藏

    2007年12月13日 #

    bootSect.S 文件中的include小問題

    在 Linux 啟動過程中,最開始加載的程序就是 bootSect.S 文件.

    其中第一行是一個include 語句:#include <asm/boot.h>
    而當我去查看boot.h的時候,發現它的真正位置在 "include/asm-i386/boot.h" 而不是 "include/ asm/boot.h"

    這讓我很不解,查網上資料也沒有解答, 打開makefile文件,仔細看了一下,終于找到原因:

    在makefile 中有這么一段:

    symlinks:
        rm 
    -f include/asm
        ( cd include ; ln 
    -sf asm-$(ARCH) asm)
        @if [ 
    ! -d include/linux/modules ]; then 
            mkdir include
    /linux/modules; 
        fi

    很明顯,首先刪除了 asm文件夾,然后 在include 下面做了一個軟連接: ln -sf asm-$(ARCH)  asm

    這里的ARCH明顯是系統相關的環境變量了,比如在i386機器上就是代表i386了。這樣asm-i386就轉成了asm.

    posted @ 2007-12-13 18:23 backup2007 閱讀(398) | 評論 (0)編輯 收藏

    2007年12月12日 #

    putty 登陸unix-center ubuntu服務器 輸入中文

    putty 登陸unix-center ubuntu服務器默認是無法輸入中文的,
    服務器上的ubuntu默認是GBK字符集,
    把putty 的font改成宋體,chinese_GB2312字符集,
    transition 里面保留默認Use font encoding 。
    重新登陸即可。

    登陸 solaris 服務器我還沒找到輸入中文的方法。

    [在~/ 建立.profile 建立環境變量]

    posted @ 2007-12-12 14:10 backup2007 閱讀(794) | 評論 (0)編輯 收藏

    2007年10月15日 #

    J2ee 程序員 需要了解的Linux知識

    版權聲明:如有轉載請求,請注明出處:http://blog.csdn.net/yzhz

             一般大型J2EE應用都在建構在linux環境下的。開發環境下我們可以通過samba映射成本地的網絡驅動器,直接在windows環境下進行編程調 試。但是最后的發布還是要到linux環境,同時我們對網上web服務器和數據庫服務器的應用管理(比如自動腳本發布等),應用監控(web服務是否正 常、mysql數據庫的使用情況)、系統監控(監控磁盤空間的使用情況等)都要求程序員熟悉必要的linux知識。
            當然程序員不必對整個linux系統樣樣精通。下面根據本人開發的經驗,列出程序員基本需要掌握的linux知識。

    一、linux的基本命令
    1、用戶管理
    userdel    刪除用戶帳號
    useradd    增加用戶賬號
    su         改變當前用戶的ID

    2、文件目錄管理
    ls         瀏覽目錄,查看當前目錄下的文件和文件名
    chmod      修改文件權限
    chown      改變文件所有者
    cp         復制文件
    cd         改變當前目錄
    mv         重命名文件或移動文件
    rm         刪除文件或者目錄
    pwd        當前目錄
    scp        遠程拷貝
    alias      別名

    3、其他命令
    ln         在文件之間建立鏈接
    tail       輸出文件內容后面的部分,一般我們會通過tail -f 實時查看當前程序打印的日志。
    type       查看一個命令所在路徑
    wc         查看行數
    grep       在文件內容中查找
    find       查找文件
    date       查看日期
    crontab     制定計劃任務,通常用于系統監控。
    df          查看磁盤剩余空間,你最好在crontab中寫個腳本監控磁盤的空間。超過90%就給相關的人員發email。
    ps          查看進程狀態
    top         查看CPU的使用率
    kill        終止進程
    killall     java程序員最喜歡用killall -9 java吧
    w           查看登錄用戶和他們正在做什么,也可以看看系統的load。load太高,就該找找原因了。
    who         查看當前用戶的便當情況
    tar         解壓或壓縮文件
    echo        控制臺輸出
    wget        http訪問
    rpm         rpm包管理

    4、重定向、管道
    5、標準輸出、標準錯誤
    6、使用"屏蔽一個特殊字符的含義
    7、正則表達式

    二、熟練掌握vim編輯器。

    三、liunx環境下shell腳本、perl腳本的編寫
    為了對網上服務器應用進行管理,通常需要編寫一些腳本。
    腳本的編寫重點掌握下面幾點:
    1、理解雙引號、單引號、反引號的含義。
    2、反斜線的使用。
    3、shell腳本賦值語句左邊的變量名不要加上$,常寫perl腳本的常犯此錯誤。
    4、字符串比較長,含有空格的時候,作為一個參數時腳本出錯,用雙引號把字符串括起來。
    5、掌握好awk和sed的用法。

    四、基本軟件包的安裝
    apache、resin、mysql
    一般的步驟就是:
    configure
    make
    make install

    五、相關網站
    下面的網站是比較優秀的linux網站,可以去看看。
    http://www.linuxforum.net/



    Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=198050

    posted @ 2007-10-15 18:11 backup2007 閱讀(435) | 評論 (0)編輯 收藏

    2007年10月14日 #

    debian JDK安裝小記

    網上不外乎兩種方法,一個是用deb包的,確實方便,一個是用傳統方法的,更加通用。
    我兩個都試過,但是在傳統方式安裝中遇到了小問題,記錄一下。

    網上的教程說,修改/etc/profile 添加環境變量,但是這個變量在重新開啟終端之后就失效了,每次重新登錄后都會失效,
    必須用 $source /etc/profile 加載才能生效。
    baidu了一下,發現/etc/profile是系統環境變量,在它之前會先加載用戶目錄下的.bashrc文件,那么我作修改:
    在~/.bashrc末尾添加  source /etc/profile ,然后$source ~/.bashrc 使之生效,這樣以后重新打開終端也可生效了。
    OK.

    posted @ 2007-10-14 16:24 backup2007 閱讀(929) | 評論 (0)編輯 收藏

    僅列出標題  下一頁
    主站蜘蛛池模板: 国产一区二区三区免费视频| 亚洲视频在线免费播放| 午夜老司机免费视频| 亚洲制服丝袜一区二区三区| 最近中文字幕2019高清免费| 亚洲AV无码久久精品成人| 97在线视频免费公开视频| 国产午夜亚洲不卡| 插鸡网站在线播放免费观看| 国产成人亚洲综合| 你是我的城池营垒免费看| 亚洲区小说区激情区图片区| 国产免费网站看v片在线| 亚洲Aⅴ无码专区在线观看q| 久久久国产精品福利免费| 久久精品国产亚洲AV无码麻豆 | 亚洲国产精品成人久久蜜臀| 国产成人综合亚洲绿色| 亚洲国产日韩在线观频| g0g0人体全免费高清大胆视频| 亚洲午夜久久久久久噜噜噜| 免费网站看av片| 亚洲人成影院在线高清| 全免费a级毛片免费看无码| 免费无码国产在线观国内自拍中文字幕| 在线看片无码永久免费aⅴ| 鲁死你资源站亚洲av| 亚洲AV无码乱码在线观看性色扶| 亚洲av成本人无码网站| 亚洲欧洲∨国产一区二区三区| 成年女人A毛片免费视频| 青青草国产免费久久久下载| 亚洲中文字幕乱码AV波多JI| 猫咪免费人成网站在线观看| 日本亚洲视频在线| 99在线在线视频免费视频观看| 亚洲综合久久1区2区3区| 成人片黄网站A毛片免费| 亚洲AV无码片一区二区三区| 亚洲国产成人精品91久久久| 久久成人18免费网站 |