posts - 0,  comments - 17,  trackbacks - 0

          一、字節(jié)和unicode

          Java內(nèi)核是unicode的,就連class文件也是,但是很多媒體,包括文件/流的保存方式是使用字節(jié)流的。因此Java要對(duì)這些字節(jié)流經(jīng)行轉(zhuǎn)化。 char是unicode的,而byte是字節(jié)。Java中byte/char互轉(zhuǎn)的函數(shù)在sun.io的包中間有。其中 ByteToCharConverter類(lèi)是中調(diào)度,可以用來(lái)告訴你,你用的convertor。其中兩個(gè)很常用的靜態(tài)函數(shù)是:

          public static ByteToCharConverter getDefault();

          public static ByteToCharConverter getConverter(String encoding);

          如果你不指定converter,則系統(tǒng)會(huì)自動(dòng)使用當(dāng)前的encoding,gb平臺(tái)上用gbk,en平臺(tái)上用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]));

          }

          結(jié)果是什么?0x4f60

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

          如果代碼改為:

          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]));

          }


          結(jié)果將又是什么?

          這就要根據(jù)平臺(tá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]));

          }

          結(jié)果是什么?0x00c4,0x00e3

          如果encoding ="8859_1",結(jié)果又是什么?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]));

          }


          結(jié)果將又是什么?還是根據(jù)平臺(tái)的編碼而定。

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

          二、utf-8

          utf-8是和unicode一一對(duì)應(yīng)的,其實(shí)現(xiàn)很簡(jiǎn)單:

          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 _ _ _ _ _ _


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

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

          0xc4e3的二進(jìn)制:

          1100 ,0100 ,1110 ,0011


          由于只有兩位我們按照兩位的編碼來(lái)排,但是我們發(fā)現(xiàn)這行不通,因?yàn)榈冢肺徊皇?因此,返回"?"

          0x4f60的二進(jìn)制:

          0100 ,1111 ,0110 ,0000

          我們用utf-8補(bǔ)齊,變成:

          1110 ,0100 ,1011 ,1101 ,1010 ,0000

          e4--bd-- a0

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


          三、string和byte[]

          string其實(shí)核心是char[],然而要把byte轉(zhuǎn)化成string,必須經(jīng)過(guò)編碼。string.length()其實(shí)就是char數(shù)組的長(zhǎng)度,如果使用不同的編碼,很可能會(huì)錯(cuò)分,造成散字和亂碼。例如:

          String encoding = “”;

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

          String str=new String(b,encoding);

          如果encoding=8859_1,會(huì)有兩個(gè)字,但是encoding=gb2312只有一個(gè)字這個(gè)問(wèn)題在處理分頁(yè)是經(jīng)常發(fā)生。

          四、Reader,Writer / InputStream,OutputStream

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

          文件test.txt只有一個(gè)"你"字,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]);

          }


          結(jié)果是什么?是"你"。如果encoding ="8859_1",結(jié)果是什么?"??"兩個(gè)字符,表示不認(rèn)識(shí)。反過(guò)來(lái)的例子自己做。

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

          Javac ?encoding


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

          String str = "你";

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

          write.write(str);

          writer.close();

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

          如果用8859_1編譯, 00c4 00e3的二進(jìn)制:

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

          因?yàn)槊總€(gè)字符都大于7位,因此用11位編碼:

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

          c1-- 84-- c3--  a3

          你會(huì)找到c1 84 c3 a3


          但是我們往往忽略掉這個(gè)參數(shù),因此這樣往往會(huì)有跨平臺(tái)的問(wèn)題:

          樣例代碼在中文平臺(tái)上編譯,生成zhclass

          樣例代碼在英文平臺(tái)上編譯,輸出enclass

          (1) zhclass在中文平臺(tái)上執(zhí)行ok,但是在英文平臺(tái)上不行

          (2) enclass在英文平臺(tái)上執(zhí)行ok,但是在中文平臺(tái)上不行

          原因是:

          (1) 在中文平臺(tái)上編譯后,其實(shí)str在運(yùn)行態(tài)的char[]是0x4f60, 在中文平臺(tái)上運(yùn)行,filewriter的缺省編碼是gb2312,因此 chartobyteconverter會(huì)自動(dòng)用調(diào)用gb2312的converter,把str轉(zhuǎn)化成byte輸入到fileoutputstream 中,于是0xc4,0xe3放進(jìn)了文件。但是如果是在英文平臺(tái)下,chartobyteconverter的缺省值是8859_1, filewriter會(huì)自動(dòng)調(diào)用8859_1去轉(zhuǎn)化str,但是他無(wú)法解釋?zhuān)虼怂麜?huì)輸出"?"

          (2) 在英文平臺(tái)上編譯后,其實(shí)str在運(yùn)行態(tài)的char[]是0x00c4 0x00e3, 在中文平臺(tái)上運(yùn)行,中文無(wú)法識(shí)別,因此會(huì)出現(xiàn)??;在英文平臺(tái)上,0x00c4-->0xc4,0x00e3->0xe3,因此 0xc4,0xe3被放進(jìn)了文件。

          六、其它原因:

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


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

          七、發(fā)生編碼的地方:

          1. 從數(shù)據(jù)庫(kù)到Java程序 byte——〉char

          2. 從Java程序到數(shù)據(jù)庫(kù) char——〉byte

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

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

          5. 從Java程序到頁(yè)面顯示 char——〉byte

          6. 從頁(yè)面form提交數(shù)據(jù)到Java程序byte——〉char

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

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

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

          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"));

          // 設(shè)置字符集?

          實(shí)際上是設(shè)置了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 {

          // 看看是否具有信息上報(bào)系統(tǒng)的權(quán)限

          if (!net.golden.uirs.util.UirsChecker.check(userId, "信息上報(bào)系統(tǒng)",

          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) 評(píng)論(0)  編輯  收藏 所屬分類(lèi): 網(wǎng)絡(luò)文摘

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

          留言簿

          隨筆檔案(1)

          文章分類(lèi)(44)

          文章檔案(46)

          收藏夾(1)

          Adobe

          AOP

          API

          appServer

          BI

          c

          • c-free
          • codeblocks
          • codelite
          • CodeLite IDE 是一個(gè)強(qiáng)大的開(kāi)源,跨平臺(tái)的 C/C++整合開(kāi)發(fā)環(huán)境. 支持包括 Windows、Linux 和 Mac 系統(tǒng)下運(yùn)行
          • codelite官網(wǎng)
          • dev-c++
          • Dev-C++是一個(gè)C&C++開(kāi)發(fā)工具,它是一款自由軟件,遵守GPL協(xié)議。
          • GCC
          • GCC 原名為 GNU C 語(yǔ)言編譯器(GNU C Compiler),因?yàn)樗局荒芴幚?C語(yǔ)言。GCC 很快地?cái)U(kuò)展,變得可處理 C++。之后也變得可處理 Fortran、Pascal、Objective-C、Java, 以及 Ada 與其他語(yǔ)言。

          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原型設(shè)計(jì)

          w3c

          Wap

          webservice

          xml

          供應(yīng)鏈管理

          博客鏈接

          好網(wǎng)站

          工作流

          開(kāi)源網(wǎng)

          招聘

          插件下載

          操作系統(tǒng)

          構(gòu)建可伸縮的系統(tǒng)

          構(gòu)建工具

          測(cè)試

          • IETest
          • IE官網(wǎng)
          • OpenSTA
          • Siege
          • Siege是一個(gè)壓力測(cè)試和評(píng)測(cè)工具,設(shè)計(jì)用于WEB開(kāi)發(fā)這評(píng)估應(yīng)用在壓力下的承受能力

          游戲

          源碼托管

          經(jīng)營(yíng)

          資源

          金融/財(cái)務(wù)

          搜索

          •  

          最新評(píng)論

          主站蜘蛛池模板: 佛冈县| 北票市| 墨玉县| 大方县| 宜城市| 辰溪县| 遵义市| 雷山县| 云林县| 隆昌县| 井冈山市| 大庆市| 吉木萨尔县| 文昌市| 株洲县| 鄂温| 惠州市| 通道| 侯马市| 淄博市| 汉源县| 阿尔山市| 丰宁| 元江| 基隆市| 漠河县| 方城县| 新安县| 简阳市| 四会市| 衡山县| 烟台市| 灯塔市| 富平县| 鄂州市| 汶上县| 财经| 宿州市| 阜康市| 康定县| 闸北区|