按字节截取含有中文汉字的字符串

要求实现一个按字节截取字符串的方法,比如对于字符串"我ZWR 爱 JAVA",截取它的前四位字节应该是"我 ZW",而不是"我ZWR",同时要保证不会出现截取了半个汉字的情况。

英文字母和中文汉字在不同的编码格式下,所占用的字节数也是不同的,我们可以通过下面的例子来看看在一些常见的编码格式下,一个英文字母和一个中文汉字分别占用多少字节。

Java代码

import java.io.UnsupportedEncodingException;

public class EncodeTest {

/**

*                        打印字符串在指定编码下的字节数和编码名称到控制台

 *

*                        @param s

*                        字符串

*                        @param encodingName

*                        编码格式

 */

public static void printByteLength(String s, String encodingName) {

System.out.print("字节数:");

 

try {

System.out.print(s.getBytes(encodingName).length);

} catch (UnsupportedEncodingException e) {

e.printStackTrace();

}

System.out.println(";编码:" + encodingName);

}

public static void main(String[] args) {

String en = "A";

String ch = "人";

// 计算一个英文字母在各种编码下的字节数

System.out.println("英文字母:" + en);

EncodeTest.printByteLength(en, "GB2312");

EncodeTest.printByteLength(en, "GBK");

EncodeTest.printByteLength(en, "GB18030");

EncodeTest.printByteLength(en, "ISO-8859-1");

EncodeTest.printByteLength(en, "UTF-8");

EncodeTest.printByteLength(en, "UTF-16");

EncodeTest.printByteLength(en, "UTF-16BE");

EncodeTest.printByteLength(en, "UTF-16LE");

System.out.println();

// 计算一个中文汉字在各种编码下的字节数

System.out.println("中文汉字:" + ch);

EncodeTest.printByteLength(ch, "GB2312");

EncodeTest.printByteLength(ch, "GBK");

EncodeTest.printByteLength(ch, "GB18030");

EncodeTest.printByteLength(ch, "ISO-8859-1");

EncodeTest.printByteLength(ch, "UTF-8");

EncodeTest.printByteLength(ch, "UTF-16");

EncodeTest.printByteLength(ch, "UTF-16BE");

EncodeTest.printByteLength(ch, "UTF-16LE");

}

}

运行结果如下:

1.英文字母:A

2.字节数:1;编码:GB2312

3.字节数:1;编码:GBK

4.字节数:1;编码:GB18030

5.字节数:1;编码:ISO-8859-1

6.字节数:1;编码:UTF-8

7.字节数:4;编码:UTF-16

8.字节数:2;编码:UTF-16BE

9.字节数:2;编码:UTF-16LE

  10.

11.中文汉字:人

12.字节数:2;编码:GB2312

13.字节数:2;编码:GBK

14.字节数:2;编码:GB18030

15.字节数:1;编码:ISO-8859-1

16.字节数:3;编码:UTF-8

17.字节数:4;编码:UTF-16

18.字节数:2;编码:UTF-16BE

19.字节数:2;编码:UTF-16LE

UTF-16BE和 UTF-16LE 是 UNICODE编码家族的两个成员。UNICODE 标准定义了

UTF-8、UTF-16、UTF-32 三种编码格式,共有

UTF-8、UTF-16、UTF-16BE、UTF-16LE、UTF-32、UTF-32BE、UTF-32LE七种编码方案。

 JAVA 所采用的编码方案是 UTF-16BE。从上例的运行结果中我们可以看出,

GB2312、GBK、GB18030 三种编码格式都可以满足题目的要求。下面我们就以 GBK编码为例来进行解答。

如果我们直接按照字节截取会出现什么情况呢?我们来测试一下:

Java代码

import java.io.UnsupportedEncodingException;  

 

public class CutString {  

    public static void main(String[] args) throws UnsupportedEncodingException {  

        String s = "我 ZWR 爱 JAVA";  

        // 获取 GBK 编码下的字节数据  

        byte[] data = s.getBytes("GBK");           byte[] tmp = new byte[6];  

        // 将 data 数组的前六个字节拷贝到 tmp 数组中  

        System.arraycopy(data, 0, tmp, 0, 6);  

        // 将截取到的前六个字节以字符串形式输出到控制台           s = new String(tmp);           System.out.println(s);  

    }  

}

输出结果:

   1. 我 ZWR?

在截取前六个字节时,第二个汉字“爱”被截取了一半,导致它无法正常显示了,这样显然是有问题的。

我们不能直接使用 String 类的 substring(intbeginIndex, int endIndex)方法,因为它是按字符截取的。'我'和'Z'都被作为一个字符来看待,length 都是 1。实际上我们只要能区分开中文汉字和英文字母,这个问题就迎刃而解了,而它们的区别就是,中文汉字是两个字节,英文字母是一个字节。

Java代码

import java.io.UnsupportedEncodingException; public class CutString {

/**

 

*                          判断是否是一个中文汉字

 *

*                          @param c

*                          字符

*                          @return true 表示是中文汉字,false 表示是英文字母

*                          @throws UnsupportedEncodingException

*                          使用了 JAVA 不支持的编码格式

 */ public static boolean isChineseChar(char c)

throws UnsupportedEncodingException {

// 如果字节数大于 1,是汉字

// 以这种方式区别英文字母和中文汉字并不是十分严谨,但在这个题目中,这样判断已经足够了

return String.valueOf(c).getBytes("GBK").length > 1;

}

/**

*                          按字节截取字符串

 *

*                          @param orignal

*                          原始字符串

*                          @param count

*                          截取位数

*                          @return 截取后的字符串

*                          @throws UnsupportedEncodingException

*                          使用了 JAVA 不支持的编码格式

 */ public static String substring(String orignal, int count)

throws UnsupportedEncodingException {

// 原始字符不为 null,也不是空字符串

if (orignal != null && !"".equals(orignal)) {

// 将原始字符串转换为 GBK 编码格式

orignal = new String(orignal.getBytes(), "GBK");

// 要截取的字节数大于 0,且小于原始字符串的字节数

if (count > 0 && count < orignal.getBytes("GBK").length) {

StringBuffer buff = new StringBuffer(); char c;

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

// charAt(int index)也是按照字符来分解字符串的 c = orignal.charAt(i); buff.append(c);

if (CutString.isChineseChar(c)) {

// 遇到中文汉字,截取字节总数减 1

--count;

}

}

return buff.toString();

}

}

return orignal;

}

public static void main(String[] args) {

// 原始字符串

String s = "我 ZWR 爱 JAVA";

System.out.println("原始字符串:" + s); try {

System.out.println("截取前 1 位:" + CutString.substring(s, 1));

System.out.println("截取前 2 位:" + CutString.substring(s, 2));

System.out.println("截取前 4 位:" + CutString.substring(s, 4));

System.out.println("截取前 6 位:" + CutString.substring(s, 6));

} catch (UnsupportedEncodingException e) {

e.printStackTrace();

}

}

}

运行结果:

1.原始字符串:我 ZWR爱 JAVA

2.截取前 1位:我

3.截取前 2位:我

4.截取前 4位:我 ZW

5.截取前 6位:我 ZWR 爱 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在Java中,字符串字节截取遇到汉字的情况需要特别处理。一般而言,一个汉字占据两个字节的存储空间。为了正确处理汉字字符串中的截取,可以使用Java的String类中的getBytes()方法来获取字符串字节数组,然后根据字节数组的长度进行截取。 具体的做法是,首先将字符串转换为字节数组,然后遍历字节数组,统计字节数,直到达到指定的截取长度。需要注意的是,若截取的最后一个字符正好是半个汉字,要将其舍弃,以保证截取后的字符串是完整的。最后,再将字节数组转换为字符串,即可得到按字节截取后的字符串。 下面是一个示例代码: ```java public static String subStringByBytes(String str, int limit) { byte[] bytes = str.getBytes(); int length = bytes.length; if (limit >= length) { return str; } int count = 0; for (int i = 0; i < limit; i++) { if ((bytes[i] & 0xFF) > 128) { count++; } } if (count % 2 != 0) { limit = limit - 1; } return new String(bytes, 0, limit); } public static void main(String[] args) { String str = "Hello, 你好!"; String newStr = subStringByBytes(str, 9); System.out.println(newStr); // 输出:Hello, 你 } ``` 在以上代码中,定义了一个`subStringByBytes`方法,该方法接受一个字符串和一个限制的字节数作为参数,并返回按字节截取后的字符串。在示例中,将字符串"Hello, 你好!"按字节截取9个字节长度,结果为"Hello, 你"。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值