2010-02-15 5 views
4

오늘 일을하고 있었고 뭔가 "재미있어 보였습니다"라는 문제를 발견했습니다. 일부 문자열 데이터를 utf-8로 해석하고 인코딩 된 양식을 확인했습니다. 데이터는 ldap (특히 Active Directory)에서 python-ldap을 통해 전송되었습니다. 거기에 놀라움이 없습니다.파이썬 UTF-16 WAVY DASH 인코딩 질문/문제

그래서 '\ xe3 \ x80 \ xb0'바이트 시퀀스가 ​​발생했습니다.이 시퀀스는 utf-8로 디코딩 될 때 유니 코드 코드 포인트 3030 (wavy dash)입니다. 나는 utf-16에서 문자열 데이터를 필요로하므로, 자연스럽게 .encode ('utf-16')를 통해 변환했습니다. IronPython의이 팬 중 하나없는 것 같다

D:\> python 
Python 2.6.4 (r264:75708, Oct 26 2009, 08:23:19) [MSC v.1500 32 bit (Intel)] on win32 
Type "help", "copyright", "credits" or "license" for more information. 
>>> u"\u3030" 
u'\u3030' 
>>> u"\u3030".encode("utf-8") 
'\xe3\x80\xb0' 
>>> u"\u3030".encode("utf-16-le") 
'00' 
>>> u"\u3030".encode("utf-16-be") 
'00' 
>>> '\xe3\x80\xb0'.decode('utf-8') 
u'\u3030' 
>>> '\xe3\x80\xb0'.decode('utf-8').encode('utf-16') 
'\xff\xfe00' 
>>> '\xe3\x80\xb0'.decode('utf-8').encode('utf-16-le').decode('utf-8') 
u'00' 

: 불행하게도, 그것은 파이썬은이 문자를 좋아하지 않는 것 같다

D:\ipy 
IronPython 2.6 Beta 2 (2.6.0.20) on .NET 2.0.50727.3053 
Type "help", "copyright", "credits" or "license" for more information. 
>>> u"\u3030" 
u'\u3030' 
>>> u"\u3030".encode('utf-8') 
u'\xe3\x80\xb0' 
>>> u"\u3030".encode('utf-16-le') 
'00' 

누군가가 말해 줄 수 있다면 무엇을, 정확히, 여기에 가고, 대단히 감사하겠습니다.

+0

좋은 질문 ... 예상되는 캐릭터의 이미지에 대한 링크가 좋은 터치입니다. –

+0

UTF-16으로 인코딩 한 다음 UTF-8을 사용하여 디코딩하면 현명한 결과가 나오지 않을 것입니다. 기껏해야 - 입력이 ASCII 인코딩 가능하다면 두 번째 문자 하나마다 합리적인 문자를 얻습니다. –

+0

네, 그 마지막 줄은 실수로 나를 혼란스럽게 만들었습니다. 감사. – NoName

답변

2

올바른 동작입니다. UTF-16으로 인코딩 된 경우 'u3030'문자는 UTF-8에서 '00'인코딩과 동일합니다. 그것은 이상하게 보입니다,하지만 맞습니다.

'\ xff \ xfe'는 (는) Byte Order Mark입니다.

다른 문자가 아닌 물결 모양의 대시를 사용 하시겠습니까? 당신이 다른 캐릭터를 원한다면 그것은 어플리케이션에 들어가기 전에 이미 잘못 인코딩 되었기 때문일 것입니다.

+0

글쎄, 간신히 문서화 된 AD LDAP 속성 인 userParameters에서 왔는데, 그 이유는 필드에 0x00과 '\ xe3 \ x80 \ xb0'콤보가 있다는 것입니다 (실제로 서로 가깝게 ...). 마이크로 소프트가 올바르게 인코딩하지 않았을 수도 있습니다. – NoName

+0

아마도''00 '대신''\ x30 \ x30' '으로 쓰면 더 명확해질 것입니다. 다른 표기법, 같은 문자열. –

+0

@NoName : \ x00을 구분 기호로 사용하고있을 가능성이 있습니다. 프로토콜에 익숙하지 않아 추측에 불과합니다. 민감한 정보가 아니라고 가정하면 여기에 전체 문자열을 게시하여 힌트를 줄 수 있습니다. –

2

하지만 괜찮 디코딩 :

>>> u"\u3030".encode("utf-16-le") 
'00' 
>>> '00'.decode("utf-16-le") 
u'\u3030' 

그것은 그 문자의 UTF-16 인코딩이 '0'에 대한 ASCII 코드에 맞춰 일어나는이다. 또한 '\ X30 \ X30'으로 나타낼 수 있습니다 :

>>> '00' == '\x30\x30' 
True 
1

당신은 여기에 두 가지를 혼동하고있다 (너무 저를 던졌다) :

  1. UTF-16 및 UTF-32 인코딩을 사용 utf-16-be 등을 통해 사용할 바이트 순서를 지정하지 않으면 BOM. 이것은 두 번째 마지막 줄에 \ xff \ xfe입니다.
  2. '00'은 digit zero 중 2 자입니다. 널 문자가 아닙니다. 즉 다른 어쨌든 인쇄 것입니다 : 샘플 코드의 기본적인 오류가 위가

    >>> '\0\0' 
    '\x00\x00' 
    
0

. 문자열 인코딩 , 당신 인코딩 유니 코드를 기억하고 당신은 에서 디코딩 다시 유니 코드로 문자열 인코딩. 그래서, 당신은 할 수 :

다음 단계로 변환
'\xe3\x80\xb0'.decode('utf-8').encode('utf-16-le').decode('utf-8') 

: 어떻게 든 UTF-16LE하지만 당신에

유 '\의 u3030'참 '00'로 인코딩됩니다
'\xe3\x80\xb0' # (some string) 
.decode('utf-8') # decode above text as UTF-8 encoded text, giving u'\u3030' 
.encode('utf-16-le') # encode u'\u3030' as UTF-16-LE, i.e. '00' 
.decode('utf-8') # OOPS! decode using the wrong encoding here! 

(2 회 아스키 영) 이것이 null 바이트 ('\ 0') 또는 무엇인지 생각하십시오.

는 기억 당신은 당신이 하나를 인코딩 할 경우 같은 문자에 도달하고 다른 인코딩과 디코딩 할 수 있습니다 :이 코드에서

>>> import unicodedata as ud 
>>> c= unichr(193) 
>>> ud.name(c) 
'LATIN CAPITAL LETTER A WITH ACUTE' 
>>> ud.name(c.encode("cp1252").decode("cp1253")) 
'GREEK CAPITAL LETTER ALPHA' 

, 나는 윈도우 1252 인코딩 및 Windows-1253에서 디코딩. 코드에서 UTF-16LE로 인코딩하고 UTF-8에서 디코딩했습니다.