将String拆分为max 1Mb size subStrings时遇到问题

时间:2017-04-20 12:05:01

标签: java string

我必须将String拆分为1Mb大小的字符串。使用UTF-8作为字符编码时,一些字母占用超过1个字节,因此为了避免在中间分割字符(例如'á'是2个字节,所以不能1个字节到最后一个字符串,1表示下一个字符串的开始)

public static List<String> cutString3(String original, int chunkSize, String encoding) throws UnsupportedEncodingException {
    List<String> strings = new ArrayList<>();
    final int end = original.length();
    int from = 0;
    int to = 0;
    do {
        to = (to + chunkSize > end) ? end : to + chunkSize;
        String chunk = original.substring(from, to); // get chunk
        while (chunk.getBytes(encoding).length > chunkSize) { // cut the chunk from the end
            chunk = original.substring(from, --to);
        }
        strings.add(chunk); // add chunk to collection
        from = to; // next chunk
    } while (to < end);
    return strings;
}

我正在使用上面的方法生成一个示例String:

private static String createDataSize(int msgSize) {
    StringBuilder sb = new StringBuilder(msgSize);
    for (int i = 0; i < msgSize; i++) {
        sb.append("a");
    }
    return sb.toString();
}

按以下方式调用方法:

String exampleString = createDataSize(1024*1024*3);
cutString(exampleString, 1024*1024, "UTF-8");

没有问题,我收回3个字符串,因为3兆字节的字符串被分成3个1兆字节的字符串。但是,如果我更改createDataSize()方法的char以将'á'附加到示例字符串,那么它只能代表“áááááá...”cutString中的内部while循环方法需要永远,因为它逐个删除每个'á',直到它适合给定的大小。我怎样才能改善内心,或者想出一些类似的解决方案呢?字符串可以小于1兆字节,只是不大!

2 个答案:

答案 0 :(得分:0)

使用二进制搜索逻辑显然符合您的需求。

简单地减少速度,仅使用块大小的一半,如果你仍然作为一些空间,添加一半,如果没有,删除一半。等等。

更简单的解决方案是仅删除chunk.getBytes(encoding).lengthchunkSize之间的差异。然后看看如果要完全填充它,你仍然可以使用多少字节。

答案 1 :(得分:0)

我很确定这是一个xy问题。没有合理的理由我可以提出将非字符附加到String(我在这里有点苛刻,欢迎评论中的例子证明我错了)。

使用get go 中的字节数组。在所需的块大小中定义它们,并插入字节,并在创建时创建块列表。转换为字符串(出于任何疯狂的原因)更容易。

如果您构建了数据缓冲区(如附加á),这显然是微不足道的。

如果您正在从文件/流中读取,这也是微不足道的!只读到字节数组。

对于后人,你用你构建内循环的方式在数据集上迭代~n ** 2次 - 对于你复制的每个字符O(完整字符串))。在每个循环中加上此过程中的编码。这会杀了你。