使用文本换行换行带字节计数

2024-05-14 17:52:20 发布

您现在位置:Python中文网/ 问答频道 /正文

如何使用textwrap模块在一行达到一定数量的字节之前进行拆分(不拆分多字节字符)?在

我想要这样的东西:

>>> textwrap.wrap('☺ ☺☺ ☺☺ ☺ ☺ ☺☺ ☺☺', bytewidth=10)
☺ ☺☺
☺☺ ☺
☺ ☺☺
☺☺

Tags: 模块数量字节字符wraptextwrapbytewidth
2条回答

结果取决于使用的编码,因为每个 字符是编码的函数,在许多编码中,字符是 还有性格。我假设我们使用的是UTF-8,其中'☺'是 编码为e298ba,长度为3个字节;给定的示例是 与这个假设一致。在

textwrap中的所有内容都对字符有效;它什么都不知道 关于编码。一种解决方法是将输入字符串转换为 另一种格式,每个字符都变成一个字符串 其长度与字节长度成正比。我用三个 字符:两个用于十六进制字节,另一个用于控制换行。 因此:

'a' -> '61x'         non-breaking
' ' -> '20 '         breaking
'☺' -> 'e2x98xbax'   non-breaking

为了简单起见,我假设我们只在空格上断开,而不是在制表符或任何地方 其他角色。在

^{pr2}$

最后我重写了textwrap的一部分,在它分割字符串后对单词进行编码。在

与Tom的解决方案不同,Python代码不需要遍历每个字符。在

def byteTextWrap(text, size, break_long_words=True):
    """Similar to textwrap.wrap(), but considers the size of strings (in bytes)
    instead of their length (in characters)."""
    try:
        words = textwrap.TextWrapper()._split_chunks(text)
    except AttributeError: # Python 2
        words = textwrap.TextWrapper()._split(text)
    words.reverse() # use it as a stack
    if sys.version_info[0] >= 3:
        words = [w.encode() for w in words]
    lines = [b'']
    while words:
        word = words.pop(-1)
        if len(word) > size:
            words.append(word[size:])
            word = word[0:size]
        if len(lines[-1]) + len(word) <= size:
            lines[-1] += word
        else:
            lines.append(word)
    if sys.version_info[0] >= 3:
        return [l.decode() for l in lines]
    else:
        return lines

相关问题 更多 >

    热门问题