2016-08-02 1 views
1

utf-8로 인코딩 된 문자열을 나타내는 바이트 배열이 있습니다. 이 바이트를 Pyton2의 문자열로 다시 디코드하려고합니다. 내 전반적인 프로그램을 위해 Python2에 의존하고 있으므로 Python3으로 전환 할 수 없습니다.어떻게 utf-8 바이트 배열을 Python2에서 문자열로 디코딩 할 수 있습니까?

array = [67, 97, 102, **-61, -87**, 32, 70, 108, 111, 114, 97] 

-> 카페 é 플로라

내가 원하는 문자열의 모든 문자가 반드시 배열에 정확히 1 바이트로 표현되지 않기 때문에, 나는 같은 솔루션을 사용할 수 없습니다

"".join(map(chr, array)) 

배열을 단계별로 실행하는 함수를 만들려고했는데 0-127 (ASCII) 범위가 아닌 숫자를 만날 때마다 새로운 16 비트 int를 만들고 현재 비트를 8 이상으로 왼쪽으로 시프트하고, 다음을 추가합니다. b 비트 OR을 사용하는 yte. 마지막으로 unichr()을 사용하여 디코드합니다.

result = [] 


for i in range(len(byte_array)): 
    x = byte_array[i] 
    if x < 0: 
     b16 = x & 0xFFFF # 16 bit 
     b16 = b16 << 8 
     b16 = b16 | byte_array[i+1] 
     result.append(unichr(m16)) 
    else: 
     result.append(chr(x)) 

return "".join(result) 

그러나 이것은 실패했습니다.

다음 기사는 아주 잘 문제를 설명하고, nodeJS 솔루션이 포함

http://ixti.net/development/node.js/2011/10/26/get-utf-8-string-from-array-of-bytes-in-node-js.html

+3

에 대한 struct.pack를 사용할 수 있습니다. – user2357112

+0

0-128의 모든 숫자를 '00'으로 "덧붙일"수는 없습니까? –

+0

inmy 대답을 볼 수 있듯이 map 및 chr 버전의 조인은 거의 작동하지만 음수의 문제는 발생합니다.내 대답은 다음과 같습니다. 동일한 가독성 높은 생성기 표현식을 사용하고 음수를 처리합니다. – jsbueno

답변

1

당신은 UTF-8 디코딩이 어떻게 작동되지 즉이

>>> a = [67, 97, 102, -61, -87, 32, 70, 108, 111, 114, 97] 
>>> struct.pack("b"*len(a),*a) 
'Caf\xc3\xa9 Flora' 
>>> print struct.pack("b"*len(a),*a).decode('utf8') 
Café Flora 
2

사용은 A bytestring에 입력을 변환하는 array module을 사용-작은 다음 decode 그것을 UTF-8을 코덱 :

import array 
decoded = array.array('b', your_input).tostring().decode('utf-8') 
+0

'ValueError : 바이트는 범위 (0, 256)에 있어야합니다. ' – wim

+0

이것은 ValueError를 제공합니다 : 바이트는 범위 (0, 256)에 있어야합니다. –

+0

@wim : 오, 허. 그들은 서명되지 않은 값 대신 입력 값을 서명했습니다. 그러면 직접 작동하지 않습니다. – user2357112

1

당신은 마음에 있어야 Python2에서 "문자열"문자에 매핑 할 일이 적절한 텍스트, 메모리의 바이트 단지 순서가 아닌 때 "인쇄" 그것들 - 바이트 순서의 의도 문자의 맵핑이 터미널의 것과 일치하면 적절한 형식의 텍스트를 볼 수 있습니다.

터미널이 UTF-8이 아닌 경우 메모리에 적절한 바이트 스트링이 있어도 인쇄하면 잘못된 결과가 표시됩니다. 그래서 표현의 끝에 추가 "디코드"단계가 필요한 이유입니다. 소스 128과 255 음수의 번호를 부호화 같이 오퍼레이터가 "CHR"를 호출하기 전에 재 정규화 값을 "경우"

text = b''.join(chr(i if i > 0 else 256 + i) for i in array).decode('utf-8') 

, 우리는 인라인있다.

"내가 원하는 문자열의 모든 문자가 배열에서 정확히 1 바이트로 표시 될 필요가 없으므로"- 그래서 - Python2.x 문자열을 사용하는 경우 처리 할 내용은 다음과 같습니다. 어쨌든 단말 올바른 tet를 다루고 싶다면 숫자를 적절한 (바이트) 문자열에 결합한 후 "decode"방법을 사용하는 것입니다 - 이것은 UTF-8 멀티 바이트 인코딩 문자에 대해 알게 될 부분입니다. (텍스트) 문자열 객체 (파이썬 2의 '유니 코드'객체) - 각 문자를 엔티티로 처리합니다.

+0

'i> i else i> 0 else 256 + i'도'i & 0xFF'라고 쓸 수 있습니다. –

+0

의미 론적 이유로 인해 작동하지 않을 수도 있습니다. 그것은 숫자를 양수로 만들기 위해 "&"작업의 부작용을 남용합니다. 어쩌면 "가장 올바른"방법은 구조체를 사용하여 @ Joran의 대답입니다.하지만 그 일의 퍼포먼스에 대해서는 확신이 서지 않습니다. 이 방법은 "문자열로 생각하는"방식입니다. :-) – jsbueno

관련 문제