2012-03-28 3 views
4

파이썬 스크립트에서 유니 코드 텍스트를 RTF 파일로 출력하려고합니다. 유니 코드는 유니 코드 UTF-16 코드 단위의 수를 나타내는 16 비트 부호 첨부 10 진수의 정수가 유를 사용하는 \ 제어 워드를 탈출 배경를 들어, Wikipedia파이썬에서 RTF 파일로 유니 코드 텍스트 출력

을 말한다. 유니 코드를 지원하지 않는 프로그램의 이점을 위해서는 지정된 코드 페이지에서이 문자를 가장 가까운 표현으로 따라야합니다. 예를 들어, \ u1576? Unicode를 지원하지 않는 구형 프로그램이 대신에 물음표로 나타내야한다는 것을 명시하는 아랍 문자 bā'b를 제공합니다.

this question on outputting RTF from Javathis one on doing so in C#도 있습니다.

그러나 내가 알 수없는 것은 파이썬에서 유니 코드 코드 포인트를 "유니 코드 UTF-16 코드 유닛 번호가있는 16 비트 부호있는 10 진 정수"로 출력하는 방법입니다. 나는 이것을 시도했다 :

for char in unicode_string: 
    print '\\' + 'u' + ord(char) + '?', 

그러나 출력은 워드 프로세서에서 열었을 때 횡설수설로 표현된다. 문제는 그것이 UTF-16 코드 번호가 아닌 것으로 보입니다. 그러나 그것을 얻는 방법을 모릅니다. 하나는 utf-16으로 인코딩 할 수 있지만 코드 번호는 어떻게 얻을 수 있습니까?

덧붙여서 PyRTF는 유니 코드 ("todo"로 표시됨)를 지원하지 않으며 pyrtf-NG가 그렇게하기로되어 있지만 해당 프로젝트가 유지 관리되지 않는 것으로 보이고 문서가 거의 없으므로주의해야합니다. 준 생산 시스템에서.

편집 : 내 실수. 위의 코드에는 두 가지 버그가 있습니다. 워블은 문자열 아래에 유니 코드 문자열이어야하며 이미 인코딩 된 문자열이 아니어야합니다. 위의 코드는 문자 사이에 공백이있는 결과를 생성합니다. 올바른 코드는 다음과 같습니다.

convertstring="" 
for char in unicode(<my_encoded_string>,'utf-8'): 
    convertstring = convertstring + '\\' + 'u' + str(ord(char)) + '?' 

이 코드는 OpenOffice에서 잘 작동합니다. 여기에 다른 사람을위한 참조로 남겨두고 있습니다 (한 가지 실수는 아래 토론 후에 추가로 수정 됨).

+1

ShankarG : Microsoft의 실제 사양은 Wikipedia의 "16 비트 부호있는 10 진 정수"표현을 사용하지 않습니다. WP 편집기와 달리 MS의 사람들은 음수 유니 코드 코드 포인트가없고 서명되었음을 알기 때문에 좋습니다. 바보가 될 것이다). 그것으로부터 취할 필요가있는 것은'\ u' 다음에 32767까지의 숫자가 필요하다는 것입니다. – geoffspear

+0

설명해 주셔서 감사합니다. 하지만 올바른 번호를 얻으려면 어떻게해야합니까? ord ()의 출력이 올바른 것 같지 않습니다. – ShankarG

+1

'ord()'는 나를 위해 '1576'을 생성하는 것 같습니다. 당신은 유니 코드 문자열이고 utf-8 바이트가 아닌지 확신합니까? – geoffspear

답변

2

최근 편집의 정보를 바탕으로이 기능이 제대로 작동한다고 생각합니다. 아래의 개선 된 버전을 제외하고.

def rtf_encode(unistr): 
    return ''.join([c if ord(c) < 128 else u'\\u' + unicode(ord(c)) + u'?' for c in unistr]) 

>>> test_unicode = u'\xa92012' 
>>> print test_unicode 
©2012 
>>> test_utf8 = test_unicode.encode('utf-8') 
>>> print test_utf8 
©2012 
>>> print rtf_encode(test_utf8.decode('utf-8')) 
\u169?2012 

이해하기 쉽도록 다른 버전이 있습니다. 유니 코드를 유지하고 그것을 join에서 유출하는 것보다 ASCII 문자열을 반환하는 것이 일관되게 만들었습니다. 또한 주석을 기반으로 수정 사항을 통합합니다. 제대로 U + 7FFF을 통해 코드 포인트를 인코딩하지거야, 나 RTF 표준에서 권장하는대로가 0x20 아래 문자를 이스케이프되므로

def rtf_encode_char(unichar): 
    code = ord(unichar) 
    if code < 128: 
     return str(unichar) 
    return '\\u' + str(code if code <= 32767 else code-65536) + '?' 

def rtf_encode(unistr): 
    return ''.join(rtf_encode_char(c) for c in unistr) 
+0

감사합니다. 비 ASCII 코드가 아닌 모든 문자를 변환하는 코드가 옳다. 실제로는 최종 출력에 영향을 미치지 않아도된다. [이] (http://effbot.org/zone/unicode-objects.htm)에 따르면 "unicode"대신 "decode"를 사용하는 것에 관해서는 두 기능이 똑같습니다. 유니 코드 (, 'utf-8')로 인코딩을 지정했습니다. – ShankarG

+0

@ShankarG,'unicode' 함수에 추가 매개 변수가 있다는 것을 알지 못했습니다. ASCII가 아닌 문자를 주었을 때 실패 할 것이라고 생각했습니다. 알려 줘서 고마워. –

+0

사실, 이것은 여전히 ​​올바르지 않습니다. RTF 표준은 * 부호있는 * 16 비트 정수를 사용하므로 32767 이상의 값은 음수 (65536 이하)로 표시됩니다. –

1

마크 랜섬의 대답은 아주 정확하지 않습니다.

파이썬 유니 코드를 rtfunicodewrote about the subject on my blog이라는 RTF 제어 코드로 인코딩하는 간단한 모듈을 만들었습니다.

요약하면, 내 방법은 정규 표현식을 사용하여 올바른 코드 포인트를 PyRTF 또는 pyrtf-ng에 포함하기에 적합한 RTF 제어 코드로 매핑합니다.

관련 문제