Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Split unicode string into 300 byte chunks without destroying characters

I want to split u"an arbitrary unicode string" into chunks of say 300 bytes without destroying any characters. The strings will be written to a socket that expects utf8 using unicode_string.encode("utf8"). I don't want to destroy any characters. How would I do this?

like image 275
runfalk Avatar asked May 18 '11 10:05

runfalk


People also ask

How do you split string into chunks?

Method #1: Using len() + loop In this, we first perform task of computation of length of each chunk required from K and string length, post that, string is splitted on desired indices to extract chunks using slicing.

How do you split a string bytes?

Solution: To split a byte string into a list of lines—each line being a byte string itself—use the Bytes. split(delimiter) method and use the Bytes newline character b'\n' as a delimiter.

How do you split a string into chunks in Python?

Python split() method is used to split the string into chunks, and it accepts one argument called separator. A separator can be any character or a symbol. If no separators are defined, then it will split the given string and whitespace will be used by default.

How do you split a string in Python with number of characters?

Python String split() Method The split() method splits a string into a list. You can specify the separator, default separator is any whitespace. Note: When maxsplit is specified, the list will contain the specified number of elements plus one.


2 Answers

UTF-8 is designed for this.

def split_utf8(s, n):
    """Split UTF-8 s into chunks of maximum length n."""
    while len(s) > n:
        k = n
        while (ord(s[k]) & 0xc0) == 0x80:
            k -= 1
        yield s[:k]
        s = s[k:]
    yield s

Not tested. But you find a place to split, then backtrack until you reach the beginning of a character.

However, if a user might ever want to see an individual chunk, you may want to split on grapheme cluster boundaries instead. This is significantly more complicated, but not intractable. For example, in "é", you might not want to split apart the "e" and the "´". Or you might not care, as long as they get stuck together again in the end.

like image 109
Dietrich Epp Avatar answered Sep 28 '22 00:09

Dietrich Epp


UTF-8 has a special property that all continuation characters are 0x800xBF (start with bits 10). So just make sure you don't split right before one.

Something along the lines of:

def split_utf8(s, n):
    if len(s) <= n:
        return s, None
    while ord(s[n]) >= 0x80 and ord(s[n]) < 0xc0:
        n -= 1
    return s[0:n], s[n:]

should do the trick.

Note: it is to be done on the encoded value, i.e. str in python 2 and bytes in python 3. The python 3 bytes.__getitem__ also includes the call to ord already, so just drop it there.

like image 41
Jan Hudec Avatar answered Sep 27 '22 22:09

Jan Hudec