我有一段代码,它打算将字符串拆分成一个字符串数组,使用chunk\u size作为拆分的大小,以字节为单位(我这样做是为了分页结果)。在大多数情况下,当字符是1字节时,这是有效的,但是当我有一个多字节字符(例如2字节的法语字符(例如é) 或者4字节的汉字)在拆分的位置,我在第一个数组元素的末尾和第二个数组元素的开头都有两个不可读的字符。
有没有一种方法可以修正代码来解释多字节字符,以便在最终结果中保留它们?
public static ArrayList<String> splitFile(String data) throws Exception {
ArrayList<String> messages = new ArrayList<>();
int CHUNK_SIZE = 400000;// 0.75mb
if (data.getBytes().length > CHUNK_SIZE) {
byte[] buffer = new byte[CHUNK_SIZE];
int start = 0, end = buffer.length;
long remaining = data.getBytes().length;
ByteArrayInputStream inputStream =
new ByteArrayInputStream(data.getBytes());
while ((inputStream.read(buffer, start, end)) != -1) {
ByteArrayOutputStream outputStream =
new ByteArrayOutputStream();
outputStream.write(buffer, start, end);
messages.add(outputStream.toString("UTF-8"));
remaining = remaining - end;
if (remaining <= end) {
end = (int) remaining;
}
}
return messages;
}
messages.add(data);
return messages;
}
3条答案
按热度按时间q1qsirdb1#
因为这样做是为了分页结果,所以不按字符而是按单词拆分文本可能很有用。您可以迭代这个
string
检查每一个单词是否至少有一半适合这一页,如果不适合,就开始新的一页。一页行大小有限的示例。在多页文档中,它的工作原理与有限的页面大小相同:
输出:
另请参阅:如何在一定长度后拆分字符串?但它应该在单词完成后分开
bwitn5fc2#
你想:
计数字符而不是字节
将regex用于块大小和字边界敏感度
少写代码
因此,
分解正则表达式:
(?s
意思是“点应该匹配新行”\G
表示“最后匹配的结束”,并初始化为输入的开始\b
意思是“单词边界”(?<=\G.{1,400000}\b)
意思是“在最后一个匹配结束之前,最多400000个字符,然后是一个单词边界”不知道你是否真的需要一个列表返回。您可以直接从拆分中返回字符串数组。
e4eetjau3#
我保留了bytearrayinputstream,就像大多数人从inputstream读取一样,而不是将所有字节都存储在内存中。
然后从
start
而不是从0开始,因为之前的块读取可能会留下一些字节。reading给出读取的字节数或-1。
最后一个ascii字符是可以的,否则我把末尾放在多字节序列的开头。也许那个序列完全被读取了,也许没有。在这里,我只是把它留到下一块正在读。
这段代码没有看到编译器。
邮件列表对内存也不友好。
顺便说一句
char[]
人们也会遇到类似的问题,有时一个unicode码位symbol是两个(utf-16)字符。