So far I come up with not so nice function:
def decodeBytesUtf8Safe(toDec):
"""
decodes byte array in utf8 to string. It can handle case when end of byte array is
not complete thus making utf8 error. in such case text is translated only up to error.
Rest of byte array (from error to end) is returned as second parameter and can be
combined with next byte array and decoded next time.
:param toDec: bytes array to be decoded a(eg bytes("abc","utf8"))
:return:
1. decoded string
2. rest of byte array which could not be encoded due to error
"""
okLen = len(toDec)
outStr = ""
while(okLen>0):
try:
outStr = toDec[:okLen].decode("utf-8")
except UnicodeDecodeError as ex:
okLen -= 1
else:
break
return outStr,toDec[okLen:]
you can test it using script:
def test(arr):
expStr = arr.decode("utf-8")
errorCnt = 0
for i in range(len(arr)+1):
decodedTxt, rest = decodeBytesUtf8Safe(arr[0:i])
decodedTxt2, rest2 = decodeBytesUtf8Safe(rest+arr[i:])
recvString = decodedTxt+decodedTxt2
sys.stdout.write("%02d ; %s (%s - %s )\n"%(i,recvString,decodedTxt, decodedTxt2))
if(expStr != recvString):
print("Error when divided at %i"%(i))
errorCnt += 1
return errorCnt
testUtf8 = bytes([0x61, 0xc5, 0xbd, 0x6c, 0x75, 0xc5, 0xa5, 0x6f, 0x75, 0xc4, 0x8d, 0x6b, 0xc3, 0xbd, 0x20, 0x6b, 0xc5, 0xaf, 0xc5, 0x88])
err = test(testUtf8)
print("total errors %i"%(err))
it shall give you the output:
00 ; aŽluťoučký kůň ( - aŽluťoučký kůň )
01 ; aŽluťoučký kůň (a - Žluťoučký kůň )
02 ; aŽluťoučký kůň (a - Žluťoučký kůň )
03 ; aŽluťoučký kůň (aŽ - luťoučký kůň )
04 ; aŽluťoučký kůň (aŽl - uťoučký kůň )
05 ; aŽluťoučký kůň (aŽlu - ťoučký kůň )
06 ; aŽluťoučký kůň (aŽlu - ťoučký kůň )
07 ; aŽluťoučký kůň (aŽluť - oučký kůň )
08 ; aŽluťoučký kůň (aŽluťo - učký kůň )
09 ; aŽluťoučký kůň (aŽluťou - čký kůň )
10 ; aŽluťoučký kůň (aŽluťou - čký kůň )
11 ; aŽluťoučký kůň (aŽluťouč - ký kůň )
12 ; aŽluťoučký kůň (aŽluťoučk - ý kůň )
13 ; aŽluťoučký kůň (aŽluťoučk - ý kůň )
14 ; aŽluťoučký kůň (aŽluťoučký - kůň )
15 ; aŽluťoučký kůň (aŽluťoučký - kůň )
16 ; aŽluťoučký kůň (aŽluťoučký k - ůň )
17 ; aŽluťoučký kůň (aŽluťoučký k - ůň )
18 ; aŽluťoučký kůň (aŽluťoučký ků - ň )
19 ; aŽluťoučký kůň (aŽluťoučký ků - ň )
20 ; aŽluťoučký kůň (aŽluťoučký kůň - )
total errors 0