按字节长度截取字符串

业务场景: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;
}

 

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

posted @ 2018-11-12 11:47  beiifeng  阅读(1990)  评论(0编辑  收藏  举报