按字节长度截取字符串

业务场景:Oracle数据字符集UTF-8,字段类型为VARCHAR2(2000)。当插入字符串的字节长度超过2000时,就会报错,使用subString(0,2000)当字符串包含中文时,也会报错,又不能直接只截取1000长度。所以需要一个根据字节长度来截取字符串的方法。

下面提供一下utf-8的截取方法:

GitHub地址 https://github.com/beiifeng/StringUtils/blob/master/StringUtils.java

/**
* 按字节长度截取字符串
*
* @param orgin 需要截取的字符串
* @param blength 需要保留的字节长度
* @param charsetName 编码,对于字符集为UTF-8的数据库,请指定编码为UTF-8;字符集为GBK的数据库,请指定编码GBK
* @return 截取后的字符串
* @throws UnsupportedEncodingException 不支持的字符编码
*/
public static String subStringb(String orgin, int blength, String charsetName) throws UnsupportedEncodingException {
return subStringb2(orgin, blength, charsetName).get(0);
}

/**
* 按字节长度分割字符串
*
* @param orgin 需要截取的字符串
* @param blength 需要保留的字节长度
* @param charsetName 编码,对于字符集为UTF-8的数据库,请指定编码为UTF-8;字符集为GBK的数据库,请指定编码GBK
* @return 分割后的字符串
* @throws UnsupportedEncodingException 不支持的字符编码
*/
public static List<String> subStringb2(String orgin, int blength, String charsetName) throws UnsupportedEncodingException {

List<String> result = new ArrayList<>();
int length;

byte[] bs = orgin.getBytes(charsetName);
while (bs.length > 0) {
length = blength;
if (length >= bs.length) {
result.add(new String(bs, 0, bs.length, charsetName));
break;
}
if ("UTF8".equals(charsetName.toUpperCase()) || "UTF-8".equals(charsetName.toUpperCase())) {
// utf8 encoding
// 0000 0000 - 0000 007F 0xxxxxxx
// 0000 0080 - 0000 07FF 110xxxxx 10xxxxxx
// 0000 0800 - 0000 FFFF 1110xxxx 10xxxxxx 10xxxxxx
// 0001 0000 - 0010 FFFF 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
while (length > 0) {
if ((bs[length] | 0x7F) == 0x7F) {
break;
}
if ((bs[length] & 0xC0) == 0xC0) {
break;
}
/*
if ((bs[length] & 0xE0) == 0xE0) {
break;
}
if ((bs[length] & 0xF0) == 0xF0) {
break;
}
*/
length--;
}
} else if ("GBK".equals(charsetName.toUpperCase())) {
boolean removLast = length % 2 == 1;
for (int i = 0; i < length; i++) {
if ((bs[i] | 0x7F) == 0x7F) {
removLast = !removLast;
}
}
if (removLast) {
length--;
}
} else if ("UNICODE".equals(charsetName.toUpperCase())) {
if (length % 2 == 1) {
length--;
}
} else if ("UTF-16".equals(charsetName.toUpperCase()) || "UTF16".equals(charsetName.toUpperCase())) {
if (length % 2 == 1) {
length--;
}
} else if ("UTF-16BE".equals(charsetName.toUpperCase())) {
if (length % 2 == 1) {
length--;
}
} else if ("UTF-16LE".equals(charsetName.toUpperCase())) {
if (length % 2 == 1) {
length--;
}
}
result.add(new String(bs, 0, length, charsetName));
bs = Arrays.copyOfRange(bs, length, bs.length);
}
    if (result.size() == 0) {
result.add("");
}
    return result;
}

 

待更新:截取结果为字符串数组。

转载于:https://www.cnblogs.com/beiifeng/p/9945626.html

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值