標籤:style blog color java 使用 io for ar
/*
需求:在java中,字串“abcd”與字串“ab你好”的長度是一樣,都是四個字元。
但對應的位元組數不同,一個漢字佔兩個位元組。
定義一個方法,按照最大的位元組數來取子串。
如:對於“ab你好”,如果取三個位元組,那麼子串就是ab與“你”字的半個,
那麼半個就要捨棄。如果去四個位元組就是“ab你”,取五個位元組還是“ab你”.
*/
代碼:其實是一個解碼和編碼的問題,要明白UTF-8碼錶和GBK碼錶的區別,UTF-8中用三個位元組代表一個漢字,GBK使用2個位元組代表一個漢字。
且在碼錶中都是用數字存放這些漢字。例如在GBK碼錶中,“你”為“-60 -29”;“好”為“-70 -61”,"謝"為"-48 -69".
我們把字串先變成位元組,按位元組截取字串。也就是先編碼成某個碼錶中的數字,然後在把數字翻譯過來,也就是查碼錶。對於GBK碼錶來說,兩個數字代表一個漢字,且一般漢字用負數代表。那麼我們可以來統計負數的個數count來決定是否捨棄半個漢字的問題,然後在判斷負數的個數的奇偶性,如果count是奇數,則截取最後一個數字,捨棄半個漢字,解碼輸出,如果是偶數,全部解碼輸出。
public class Test { /** * @param args * @throws IOException */ public static void main(String[] args) throws IOException { String str = "ab你好cd謝謝";// 97 98 -60 -29 -70 -61 99 100 -48 -69 -48 -69 int len = str.getBytes("gbk").length; for(int x=0; x<len; x++){ System.out.println("截取"+(x+1)+"個位元組結果是:"+cutStringByByte(str, x+1)); } // int len = str.getBytes("utf-8").length; // for(int x=0; x<len; x++){// System.out.println("截取"+(x+1)+"個位元組結果是:"+cutStringByU8Byte(str, x+1));// } } /* String str1 = "琲";//-84 105
byte[] buf = str1.getBytes("gbk");
for(byte b : buf){
System.out.print(" "+b);//-84 105
*/ /** * 使用Utf-8按照位元組截取字串,Utf-8用3個位元組代表一個漢字。 */ public static String cutStringByU8Byte(String str, int len) throws IOException { byte[] buf = str.getBytes("utf-8");//編碼 System.out.println(buf); int count = 0; for(int x=len-1; x>=0; x--){ if(buf[x]<0) count++; else break; } if(count%3==0) return new String(buf,0,len,"utf-8");//解碼 else if(count%3==1) return new String(buf,0,len-1,"utf-8"); else return new String(buf,0,len-2,"utf-8"); } /** * 使用位元組截取字串,gbk預設一個漢字為2個位元組,編碼錶用兩個數字代表一個漢字。 * (60 -29 -70 -61)代表你好 * 思路:我們可以記錄負數的個數, * 如果數位個數為偶數,不用截取,沒有半個漢字的情況, * 如果負數的個數為奇數,那麼加入有5個數字,那麼最後一個數字捨棄。變為4個數字,再解碼。 * @param str * @param len * @return * @throws IOException */ public static String cutStringByByte(String str,int len) throws IOException{ byte[] buf = str.getBytes("gbk");//把指定編碼的字串轉化為位元組,存放到位元組數組中,編碼 int count = 0; for(int x=len-1; x>=0; x--){//從數組的最後面開始迴圈,記錄負數的個數 if(buf[x]<0)//漢字的編碼錶為負數 count++; else break; } if(count%2==0)//負數的個數為偶數,不截取 return new String(buf,0,len,"gbk");//解碼 else return new String(buf,0,len-1,"gbk");//捨棄一位元字,解碼 }}