小弟在对接业务的时候 要求将数据写入文件,GBK格式,上传,下载也是GBK的。但出现了一种情况,获取文件中一行内容后,截取一段有中文的数据,就会出现 截取结果的长度要大于输入的长度,比如我截取6个字符长度,但实际却截取了8个长度。截取方法是String的subString方法。
仔细查看后才知道,subString的方法是默认将字符都处理成--UCS2字符,所以长度会有变化。
经过一番查找最后得出 ,要截取字符串之前都需要对字符进行处理
以下是代码
public static void main(String args[]) throws UnsupportedEncodingException { String str = "我ABC。汉DEF"; System.out.println("-----字符串的字节长度是:"+str.getBytes().length+"-----"); char[] arr = str.toCharArray(); //测试isNotChinese方法 char aaa = '。'; System.out.println("====第一个字符是否是汉字?"+isNotChinese(aaa)+"==,很明显 不认识中文标点符号==="); System.out.println("====第二个字符是否是汉字?"+isNotChinese(arr[1])+"====="); //汉字个数---测试isChinese方法 int count = 0; for (int i = 0; i < arr.length; i++) { char ai = arr[i]; if(isChinese(ai)){ count++; } } System.out.println("----判断有几个汉字-----"); System.out.println(count); //截取指定开始位置 和长度的字节,可转换成GBK System.out.println(btyeSubstring(str,6,0)); } /** * 按照字节对字符串进行截取 * @param str * @param count * @param start * @return * @throws UnsupportedEncodingException */ public static String btyeSubstring(String str,int count,int start) throws UnsupportedEncodingException { //串不能为空 if(null != str && !"".equals(str)){ //对参数进行字符转换 str = new String(str.getBytes(),"UTF-8"); //判断要截取的字节数 if(count > 0 && count < str.getBytes("UTF-8").length){ StringBuilder buff = new StringBuilder(); char c; for(int i = start; i < count; i++){ //按照需要截取的长度 0-count 进行截取,char类型,按字节截取 c = str.charAt(i); buff.append(c); //判断c 是不是汉字,如果是,则截取的长度要缩减1 if(isChinese(c)){ --count; } } return new String(buff.toString().getBytes(),"UTF-8"); } } return str; } /** * 判断是否是中文相关字符 * @param c * @return */ public static boolean isChinese(char c) { Character.UnicodeBlock ub = Character.UnicodeBlock.of(c); if (ub == Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS || ub == Character.UnicodeBlock.CJK_COMPATIBILITY_IDEOGRAPHS || ub == Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS_EXTENSION_A || ub == Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS_EXTENSION_B || ub == Character.UnicodeBlock.CJK_SYMBOLS_AND_PUNCTUATION || ub == Character.UnicodeBlock.HALFWIDTH_AND_FULLWIDTH_FORMS || ub == Character.UnicodeBlock.GENERAL_PUNCTUATION) { return true; } return false; } /** * 判断汉字,不能判断中文符号 * @param c * @return */ public static boolean isNotChinese(char c){ //0x4E00 0x9FA5是汉字在unicode 16进制编码中的区间值 return (c >= 0x4E00 && c <= 0x9FA5) ? true : false; }
注意:0x4E00 ,0x9FA5是汉字在unicode 16进制编码中的区间值,判断汉字足够,但判断中文标点就不行了。需要使用Character.UnicodeBlock 指定的属性进行判断。