隨筆 - 312, 文章 - 14, 評(píng)論 - 1393, 引用 - 0
          數(shù)據(jù)加載中……

          用Java實(shí)現(xiàn)按字節(jié)長(zhǎng)度截取字符串的方法

          本文為原創(chuàng),如需轉(zhuǎn)載,請(qǐng)注明作者和出處,謝謝!

            Web應(yīng)用程序在瀏覽器中顯示字符串時(shí),由于顯示長(zhǎng)度的限制,常常需要將字符串截取后再進(jìn)行顯示。但目前很多流行的語(yǔ)言,如C#、Java內(nèi)部采用的都是 Unicode 16(UCS2)編碼,在這種編碼中所有的字符都是兩個(gè)字符,因此,如果要截取的字符串是中、英文、數(shù)字混合的,就會(huì)產(chǎn)生問(wèn)題,如下面的字符串:

          String s = "a加b等于c,如果a等1、b等于2,那么c等3";

            上面的字符串既有漢字,又有英文字符和數(shù)字。如果要截取前6個(gè)字節(jié)的字符,應(yīng)該是”a加b等",但如果用substring方法截取前6個(gè)字符就成了"a 加b等于c"。產(chǎn)生這個(gè)問(wèn)題的原因是將substring方法將雙字節(jié)的漢字當(dāng)成一個(gè)字節(jié)的字符(UCS2字符)處理了。 要解決這個(gè)問(wèn)題的方法是首先得到該字符串的UCS2編碼的字節(jié)數(shù)組,如下面的代碼如下:

          byte[] bytes = s.getBytes("Unicode");

              由于上面生成的字節(jié)數(shù)組中前兩個(gè)字節(jié)是標(biāo)志位,bytes[0] = -2,bytes[1] = -1,因此,要從第三個(gè)字節(jié)開始掃描,對(duì)于一個(gè)英文或數(shù)字字符,UCS2編碼的第二個(gè)字節(jié)是相應(yīng)的ASCII,第一個(gè)字節(jié)是0,如a的UCS2編碼是0  97,而漢字兩個(gè)字節(jié)都不為0,因此,可以利于UCS2編碼的這個(gè)規(guī)則來(lái)計(jì)算實(shí)際的字節(jié)數(shù),該方法的實(shí)現(xiàn)代碼如下:

              public static String bSubstring(String s, int length) throws Exception
              {

                  
          byte[] bytes = s.getBytes("Unicode");
                  
          int n = 0// 表示當(dāng)前的字節(jié)數(shù)
                  int i = 2// 要截取的字節(jié)數(shù),從第3個(gè)字節(jié)開始
                  for (; i < bytes.length && n < length; i++)
                  {
                      
          // 奇數(shù)位置,如3、5、7等,為UCS2編碼中兩個(gè)字節(jié)的第二個(gè)字節(jié)
                      if (i % 2 == 1)
                      {
                          n
          ++// 在UCS2第二個(gè)字節(jié)時(shí)n加1
                      }
                      
          else
                      {
                          
          // 當(dāng)UCS2編碼的第一個(gè)字節(jié)不等于0時(shí),該UCS2字符為漢字,一個(gè)漢字算兩個(gè)字節(jié)
                          if (bytes[i] != 0)
                          {
                              n
          ++;
                          }
                      }
                  }
                  
          // 如果i為奇數(shù)時(shí),處理成偶數(shù)
                  if (i % 2 == 1)

                  {
                      
          // 該UCS2字符是漢字時(shí),去掉這個(gè)截一半的漢字
                      if (bytes[i - 1] != 0)
                          i 
          = i - 1;
                      
          // 該UCS2字符是字母或數(shù)字,則保留該字符
                      else
                          i 
          = i + 1;
                  }

                  
          return new String(bytes, 0, i, "Unicode");
              }

              下面代碼使用了bSubstring方法:

          String s = "a加b等于c,如果a等1、b等于2,那么c等3";
          System.out.println(bSubstring(s,
          6));

              上面的代碼截取的字符串是"a加b等"




          Android開發(fā)完全講義(第2版)(本書版權(quán)已輸出到臺(tái)灣)

          http://product.dangdang.com/product.aspx?product_id=22741502



          Android高薪之路:Android程序員面試寶典 http://book.360buy.com/10970314.html


          新浪微博:http://t.sina.com.cn/androidguy   昵稱:李寧_Lining

          posted on 2008-09-07 09:46 銀河使者 閱讀(11586) 評(píng)論(11)  編輯  收藏 所屬分類: javaweb 原創(chuàng)

          評(píng)論

          # re: 用Java實(shí)現(xiàn)按字節(jié)長(zhǎng)度截取字符串的方法  回復(fù)  更多評(píng)論   

          String s = "a加b等于c,如果a等1、b等于2,那么c等3";
          System.out.println(bSubstring(s, 5));
          這個(gè)返回什么?
          2008-09-07 15:58 | Lau Jeffrey

          # re: 用Java實(shí)現(xiàn)按字節(jié)長(zhǎng)度截取字符串的方法  回復(fù)  更多評(píng)論   

          to Lau Jeffrey

          由于前5個(gè)字節(jié),第5個(gè)字節(jié)將漢字截取一半,所以把這個(gè)漢字去了,返回“a加b"

          如果想將截一半的漢字要保留,可以將
          if (i % 2 == 1)

          {
          // 該UCS2字符是漢字時(shí),去掉這個(gè)截一半的漢字
          if (bytes[i - 1] != 0)
          i = i - 1;
          // 該UCS2字符是字母或數(shù)字,則保留該字符
          else
          i = i + 1;
          }
          {
          // 該UCS2字符是漢字時(shí),去掉這個(gè)截一半的漢字
          if (bytes[i - 1] != 0)
          i = i - 1;
          // 該UCS2字符是字母或數(shù)字,則保留該字符
          else
          i = i + 1;
          }

          改成
          if (i % 2 == 1)
          {
          i = i + 1;
          }
          2008-09-08 08:51 | 銀河使者

          # re: 用Java實(shí)現(xiàn)按字節(jié)長(zhǎng)度截取字符串的方法  回復(fù)  更多評(píng)論   

          路過(guò),呵呵
          2008-09-08 11:56 | Fingki.li

          # re: 用Java實(shí)現(xiàn)按字節(jié)長(zhǎng)度截取字符串的方法  回復(fù)  更多評(píng)論   

          非常不錯(cuò)。頂一下
          2008-09-09 17:51 |

          # re: 用Java實(shí)現(xiàn)按字節(jié)長(zhǎng)度截取字符串的方法  回復(fù)  更多評(píng)論   

          你好,認(rèn)識(shí)一下,我是stevenjk,在csai的同城拜師看到你的信息,我也在遼寧沈陽(yáng)。
          http://www.educity.cn/56bs/teacherlist.asp?province=%C1%C9%C4%FE
          2008-09-26 14:21 | stevenjk

          # re: 用Java實(shí)現(xiàn)按字節(jié)長(zhǎng)度截取字符串的方法  回復(fù)  更多評(píng)論   

          你好,很高興認(rèn)識(shí)你。如果你有聯(lián)系方式,可以在我的blog里私人留言。 I'm glad to see you.
          2008-09-26 14:48 | 銀河使者

          # re: 用Java實(shí)現(xiàn)按字節(jié)長(zhǎng)度截取字符串的方法  回復(fù)  更多評(píng)論   

          你好,你寫的文章都很精辟,通俗易懂,我學(xué)到了很多。針對(duì)這個(gè)方法我進(jìn)行調(diào)試發(fā)現(xiàn)和你說(shuō)的有一點(diǎn)不相符的地方,就是bytes[0] = -1,bytes[1] = -2,不知道是怎么回事,是否和系統(tǒng)編碼有關(guān)系呢,希望能夠給以解答,在這里先謝謝了
          2009-04-01 16:53 | xiasheng

          # re: 用Java實(shí)現(xiàn)按字節(jié)長(zhǎng)度截取字符串的方法  回復(fù)  更多評(píng)論   

          寫的很詳細(xì) ,學(xué)習(xí)了
          2010-12-13 16:15 | aw

          # re: 用Java實(shí)現(xiàn)按字節(jié)長(zhǎng)度截取字符串的方法  回復(fù)  更多評(píng)論   

          呵呵,學(xué)習(xí)ing。對(duì)于這個(gè)真不了解。
          2012-06-15 20:19 | 紅淚

          # re: 用Java實(shí)現(xiàn)按字節(jié)長(zhǎng)度截取字符串的方法[未登錄](méi)  回復(fù)  更多評(píng)論   

          GBK編碼java代碼,感覺(jué)總是少兩個(gè)字符
          String s = "abc中文123";
          System.out.println(bSubstring(s, 3));

          我的環(huán)境打印出來(lái)是:a,而不是想象的abc,很怪異,麻煩老師看下,謝謝
          2013-05-20 16:46 | bruce

          # re: 用Java實(shí)現(xiàn)按字節(jié)長(zhǎng)度截取字符串的方法[未登錄](méi)  回復(fù)  更多評(píng)論   

          int i=6;//想截取的位數(shù)
          while(name.getBytes().length>6) {
          name = name.substring(0, i--);
          }
          直接也好用了
          2014-01-03 11:40 | 小菜鳥
          主站蜘蛛池模板: 建阳市| 永康市| 黎平县| 天气| 积石山| 兴和县| 西吉县| 鹿泉市| 黑河市| 宜昌市| 宜城市| 上蔡县| 彭州市| 阳江市| 蓬莱市| 新余市| 梨树县| 三亚市| 岳池县| 中牟县| 龙井市| 奉贤区| 古蔺县| 盐山县| 沭阳县| 嵩明县| 青河县| 马鞍山市| 深州市| 苏州市| 平顶山市| 桑植县| 乌兰县| 南郑县| 绥阳县| 青海省| 阳春市| 枣庄市| 当涂县| 吴江市| 阳高县|