/**
* 方法:字符串按字节固定长度分割数组
* startPos 子串在原字符串字节数组的开始截取下标
* startStrPos 子串在原字符串开始截取的下标
* strLen 原字符串字节数组长度
* 背景:由于编码格式不同,直接截取可能会拿到一个被砍一半的乱码,如utf-8 4byte 一个中文,如果截取的时候是5byte,就会出现乱码
* 原理:1、先按字节数组进行截取,获得一个长度不大于固定截取长度的字节数组
* 2、把字节数组转字符串得到一个新子串,再转byte数组后,两数组长度进行比较(新子串再转byte数组时,会对截取了一半的字符进行补全为对应编码集一个字符的长度),
* 如果新子串的字节数组比按长度截取的子串字节数组长,说明存在截取一半的字符,这个字符会在最后一个位置,要舍弃
* 所以,新子串按字符串长度截取减少1位,得到的字符串就是没有截取一半的字符,且长度小于等于需要的字节长度的子串。
*
* 1.当 子串字节数组开始截取下标 小于 原字符串字节数组长度 一直循环
* 2.子串字节数组大小 需要根据 当前父串字节数组的截取下标和长度差值 与 预想截取的字节长度 比较来创建(否则用System.arraycopy会报错)
* 3.根据 子串在原字符串字节数组的开始截取下标 拷贝父字节数组的内容到子字节数组
* 4.根据 子串在原字符串开始截取的下标 与 子字节数组转为字符串的长度 在父字符串截取一个伪子串(可能最后一个字符被截取一半是乱码)
* 5.比较伪子串转字节数组后长度 与 预想截取的字节数组长度,大于,则伪子串截取字符串长度-1
* 6.子串字节数组开始截取下标 + 得到的子串字节长度;子串在原字符串开始截取的下标 + 得到子串的字符长度
* @param str 原字符串
* @param len 分割字串字节长度
* @param charSet 编码字符集
* @return List<String> 分割后的子串
* @throws UnsupportedEncodingException
*/
public static final List<String> divideStrByBytes(String str, int len, String charSet) throws UnsupportedEncodingException{
List<String> strSection = new ArrayList<>();
byte[] bt = str.getBytes(charSet);
int strLen = bt.length;
int startPos = 0;
int startStrPos = 0;
while (startPos < strLen) {
Integer subSectionLen = len;
if (strLen - startPos < len) {
subSectionLen = strLen - startPos;
}
byte[] br = new byte[subSectionLen];
System.arraycopy(bt, startPos, br, 0, subSectionLen);
String res = new String(br, charSet);
int resLen = res.length();
if (str.substring(startStrPos, startStrPos + resLen).getBytes(charSet).length > len) {
res = res.substring(0, resLen - 1);
}
startStrPos += res.length();
strSection.add(res);
startPos += res.getBytes(charSet).length;
}
return strSection;
}
java 字符串固定长度切割
最新推荐文章于 2024-12-06 16:03:54 发布