posts - 0,  comments - 17,  trackbacks - 0

          一、字節和unicode

          Java內核是unicode的,就連class文件也是,但是很多媒體,包括文件/流的保存方式是使用字節流的。因此Java要對這些字節流經行轉化。 char是unicode的,而byte是字節。Java中byte/char互轉的函數在sun.io的包中間有。其中 ByteToCharConverter類是中調度,可以用來告訴你,你用的convertor。其中兩個很常用的靜態函數是:

          public static ByteToCharConverter getDefault();

          public static ByteToCharConverter getConverter(String encoding);

          如果你不指定converter,則系統會自動使用當前的encoding,gb平臺上用gbk,en平臺上用8859_1。

          byte ——〉char:

          "你"的gb碼是:0xc4e3 ,unicode是0x4f60

          String encoding = "gb2312";

          byte b[] = {(byte)''"u00c4'',(byte)''"u00e3''};

          ByteToCharConverter converter = ByteToCharConverter.getConverter(encoding);

          char c[] = converter.convertAll(b);

          for (int i = 0; i < c.length; i++) {

          System.out.println(Integer.toHexString(c[i]));

          }

          結果是什么?0x4f60

          如果encoding ="8859_1",結果又是什么?0x00c4,0x00e3(這表明8859_1是以字節為單位的)

          如果代碼改為:

          byte b[] = {(byte)''"u00c4'',(byte)''"u00e3''};

          ByteToCharConverter converter = ByteToCharConverter. getDefault();

          char c[] = converter.convertAll(b);

          for (int i = 0; i < c.length; i++) {

          System.out.println(Integer.toHexString(c[i]));

          }


          結果將又是什么?

          這就要根據平臺的編碼而定。

          char ——〉byte:

          String encoding = "gb2312";

          char c[] = {''"u4f60''};

          CharToByteConverter converter = CharToByteConverter.getConverter(encoding);

          byte b[] = converter.convertAll(c);

          for (int i = 0; i < b.length; i++) {

          System.out.println(Integer.toHexString(b[i]));

          }

          結果是什么?0x00c4,0x00e3

          如果encoding ="8859_1",結果又是什么?0x3f

          如果代碼改為

          String encoding = "gb2312";

          char c[] = {''"u4f60''};

          CharToByteConverter converter = CharToByteConverter.getDefault();

          byte b[] = converter.convertAll(c);

          for (int i = 0; i < b.length; i++) {

          System.out.println(Integer.toHexString(b[i]));

          }


          結果將又是什么?還是根據平臺的編碼而定。

          很多中文問題就是從這兩個最簡單的類派生出來的。而卻有很多類不直接支持把encoding輸入,這給我們帶來諸多不便。很多程序難得用encoding了,直接用default的encoding,這就給我們移植帶來了很多困難。

          二、utf-8

          utf-8是和unicode一一對應的,其實現很簡單:

          7位的unicode: 0 _ _ _ _ _ _ _

          11位的unicode: 1 1 0 _ _ _ _ _ 1 0 _ _ _ _ _ _

          16位的unicode: 1 1 1 0 _ _ _ _ 1 0 _ _ _ _ _ _ 1 0 _ _ _ _ _ _

          21位的unicode: 1 1 1 1 0 _ _ _ 1 0 _ _ _ _ _ _ 1 0 _ _ _ _ _ _ 1 0 _ _ _ _ _ _


          大多數情況是只使用到16位以下的unicode:

          "你"的gb碼是:0xc4e3 ,unicode是0x4f60

          0xc4e3的二進制:

          1100 ,0100 ,1110 ,0011


          由于只有兩位我們按照兩位的編碼來排,但是我們發現這行不通,因為第7位不是0因此,返回"?"

          0x4f60的二進制:

          0100 ,1111 ,0110 ,0000

          我們用utf-8補齊,變成:

          1110 ,0100 ,1011 ,1101 ,1010 ,0000

          e4--bd-- a0

          于是返回:0xe4,0xbd,0xa0。


          三、string和byte[]

          string其實核心是char[],然而要把byte轉化成string,必須經過編碼。string.length()其實就是char數組的長度,如果使用不同的編碼,很可能會錯分,造成散字和亂碼。例如:

          String encoding = “”;

          byte [] b={(byte)''"u00c4'',(byte)''"u00e3''};

          String str=new String(b,encoding);

          如果encoding=8859_1,會有兩個字,但是encoding=gb2312只有一個字這個問題在處理分頁是經常發生。

          四、Reader,Writer / InputStream,OutputStream

          Reader和Writer核心是char,InputStream和OutputStream核心是byte。但是Reader和Writer的主要目的是要把char讀/寫InputStream/OutputStream。例如:

          文件test.txt只有一個"你"字,0xc4,0xe3

          String encoding = "gb2312";

          InputStreamReader reader = new InputStreamReader(new FileInputStream(

          "text.txt"), encoding);

          char c[] = new char[10];

          int length = reader.read(c);

          for (int i = 0; i < length; i++) {

          System.out.println(c[i]);

          }


          結果是什么?是"你"。如果encoding ="8859_1",結果是什么?"??"兩個字符,表示不認識。反過來的例子自己做。

          五、我們要對Java的編譯器有所了解:

          Javac ?encoding


          我們常常沒有用到encoding這個參數。其實encoding這個參數對于跨平臺的操作是很重要的。如果沒有指定encoding,則按照系統的默認encoding,gb平臺上是gb2312,英文平臺上是iso8859_1。Java的編譯器實際上是調用 sun.tools.Javac.main的類,對文件進行編譯,這個類有compile函數中間有一個encoding的變量,-encoding的參 數其實直接傳給encoding變量。編譯器就是根據這個變量來讀取Java文件的,然后把用utf-8形式編譯成class文件。例子代碼:

          String str = "你";

          FileWriter writer = new FileWriter("text.txt");

          write.write(str);

          writer.close();

          如果用gb2312編譯,你會找到e4 bd a0的字段 ;

          如果用8859_1編譯, 00c4 00e3的二進制:

          0000,0000 ,1100,0100 ,0000,0000 ,1110,0011

          因為每個字符都大于7位,因此用11位編碼:

          1100,0001,1000,0100,1100,0011,1010,0011

          c1-- 84-- c3--  a3

          你會找到c1 84 c3 a3


          但是我們往往忽略掉這個參數,因此這樣往往會有跨平臺的問題:

          樣例代碼在中文平臺上編譯,生成zhclass

          樣例代碼在英文平臺上編譯,輸出enclass

          (1) zhclass在中文平臺上執行ok,但是在英文平臺上不行

          (2) enclass在英文平臺上執行ok,但是在中文平臺上不行

          原因是:

          (1) 在中文平臺上編譯后,其實str在運行態的char[]是0x4f60, 在中文平臺上運行,filewriter的缺省編碼是gb2312,因此 chartobyteconverter會自動用調用gb2312的converter,把str轉化成byte輸入到fileoutputstream 中,于是0xc4,0xe3放進了文件。但是如果是在英文平臺下,chartobyteconverter的缺省值是8859_1, filewriter會自動調用8859_1去轉化str,但是他無法解釋,因此他會輸出"?"

          (2) 在英文平臺上編譯后,其實str在運行態的char[]是0x00c4 0x00e3, 在中文平臺上運行,中文無法識別,因此會出現??;在英文平臺上,0x00c4-->0xc4,0x00e3->0xe3,因此 0xc4,0xe3被放進了文件。

          六、其它原因:

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


          設置瀏覽器的顯示編碼,如果response的數據是utf8編碼,顯示將是亂碼,但是亂碼和上述原因還不一樣。

          七、發生編碼的地方:

          1. 從數據庫到Java程序 byte——〉char

          2. 從Java程序到數據庫 char——〉byte

          3. 從文件到Java程序 byte——〉char

          4. 從Java程序到文件 char——〉byte

          5. 從Java程序到頁面顯示 char——〉byte

          6. 從頁面form提交數據到Java程序byte——〉char

          7. 從流到Java程序byte——〉char

          8. 從Java程序到流char——〉byte

          可以使用配置過濾器的方法解決中文亂碼的:

          RequestFilter

          net.golden.uirs.util.RequestFilter

          charset

          gb2312

          RequestFilter

          *.Jsp

          public void doFilter(ServletRequest req, ServletResponse res,

          FilterChain fChain) throws IOException, ServletException {

          HttpServletRequest request = (HttpServletRequest) req;

          HttpServletResponse response = (HttpServletResponse) res;

          HttpSession session = request.getSession();

          String userId = (String) session.getAttribute("userid");

          req.setCharacterEncoding(this.filterConfig.getInitParameter("charset"));

          // 設置字符集?

          實際上是設置了byte ——〉char的encoding

          try {

          if (userId == null || userId.equals("")) {

          if (!request.getRequestURL().toString().matches(

          ".*/uirs/logon/logon(Controller){0,1}""x2EJsp$")) {

          session.invalidate();

          response.sendRedirect(request.getContextPath() +

          "/uirs/logon/logon.Jsp");

          }

          }

          else {

          // 看看是否具有信息上報系統的權限

          if (!net.golden.uirs.util.UirsChecker.check(userId, "信息上報系統",

          net.golden.uirs.util.UirsChecker.ACTION_DO)) {

          if (!request.getRequestURL().toString().matches(

          ".*/uirs/logon/logon(Controller){0,1}""x2EJsp$")) {

          response.sendRedirect(request.getContextPath() +

          "/uirs/logon/logonController.Jsp");

          }

          }

          }

          }

          catch (Exception ex) {

          response.sendRedirect(request.getContextPath() +

          "/uirs/logon/logon.Jsp");

          }

          fChain.doFilter(req, res);

          }

          posted on 2007-12-17 16:07 xyz 閱讀(442) 評論(0)  編輯  收藏 所屬分類: 網絡文摘

          <2025年6月>
          25262728293031
          1234567
          891011121314
          15161718192021
          22232425262728
          293012345

          留言簿

          隨筆檔案(1)

          文章分類(44)

          文章檔案(46)

          收藏夾(1)

          Adobe

          AOP

          API

          appServer

          BI

          c

          • c-free
          • codeblocks
          • codelite
          • CodeLite IDE 是一個強大的開源,跨平臺的 C/C++整合開發環境. 支持包括 Windows、Linux 和 Mac 系統下運行
          • codelite官網
          • dev-c++
          • Dev-C++是一個C&C++開發工具,它是一款自由軟件,遵守GPL協議。
          • GCC
          • GCC 原名為 GNU C 語言編譯器(GNU C Compiler),因為它原本只能處理 C語言。GCC 很快地擴展,變得可處理 C++。之后也變得可處理 Fortran、Pascal、Objective-C、Java, 以及 Ada 與其他語言。

          Cache

          CMS

          DB

          eclipse

          FreeMarker

          hibernate

          html5

          ibatis

          java

          jquery

          js

          json

          Linux

          Log

          mail server

          mobile

          mysql

          oauth

          openID

          other

          PHP

          portal

          report

          Scheduler

          schema

          Security

          SOA

          spring

          struts

          UI原型設計

          w3c

          Wap

          webservice

          xml

          供應鏈管理

          博客鏈接

          好網站

          工作流

          開源網

          招聘

          插件下載

          操作系統

          構建可伸縮的系統

          構建工具

          測試

          • IETest
          • IE官網
          • OpenSTA
          • Siege
          • Siege是一個壓力測試和評測工具,設計用于WEB開發這評估應用在壓力下的承受能力

          游戲

          源碼托管

          經營

          資源

          金融/財務

          搜索

          •  

          最新評論

          主站蜘蛛池模板: 日土县| 剑川县| 曲阜市| 城市| 建昌县| 黑水县| 肃北| 信丰县| 新竹市| 自贡市| 泉州市| 海口市| 柯坪县| 哈密市| 准格尔旗| 辽宁省| 宁晋县| 台东市| 加查县| 天全县| 霍山县| 潜山县| 大名县| 隆昌县| 抚州市| 深水埗区| 石屏县| 金湖县| 谢通门县| 新沂市| 海口市| 定兴县| 永春县| 隆子县| 轮台县| 高邑县| 磐安县| 文成县| 滁州市| 射洪县| 腾冲县|