Вопрос по python, unicode, rtf – Проблема со знаком евро при чтении файла RTF с Python

2

Мне нужно создать документ в RTF с использованием Python и pyRTF, все в порядке: у меня нет проблем с акцентированными буквами, он принимает даже знак евро без ошибок, но вместоЯ получаю этот знак:¤. I encode the strings in this way:

x.encode("iso-8859-15")

Я много гуглил, но не смог решить эту проблему, что мне нужно сделать, чтобы получить знак евро?

Не меняйте название; скорее, отметьте правильный ответ (ищите знак V под оценкой ответа слева). Martijn Pieters♦

Ваш Ответ

2   ответа
0

Хорошей новостью является то, что вы не делаете ничего плохого. Плохая новость заключается в том, что RTF читается как ISO 8859-1 независимо.

>>> print u'€'.encode('iso-8859-15').decode('iso-8859-1')
¤

Вам нужно будет использоватьUnicode escape если вы хотите, чтобы он был прочитан правильно.

>>> print hex(ord(u'€'))
0x20ac
RTF фактически не использует стандартную кодировку; Microsoft изобрелаnew кодировка для поддержки не-ASCII символов вместо.
5

Стандарт RTF использует UTF-16, но имеет форму, соответствующую формату последовательности команд RTF. Документально наhttp://en.wikipedia.org/wiki/Rich_Text_Format#Character_encoding, К сожалению, pyRTF не выполняет никакой кодировки для вас; обработка этого была на проекте TODO, но, очевидно, они никогда не добирались до этого, прежде чем покинуть библиотеку.

Это основано на коде, который я недавно использовал в проекте. Я выпустил это какrtfunicode on PyPI, с поддержкой Python 2 и 3; версия Python 2:

import codecs
import re

_charescape = re.compile(u'([\x00-\x1f\\\\{}\x80-\uffff])')
def _replace(match):
    codepoint = ord(match.group(1))
    # Convert codepoint into a signed integer, insert into escape sequence
    return '\\u%s?' % (codepoint if codepoint < 32768 else codepoint - 65536)    


def rtfunicode_encode(text, errors):
    # Encode to RTF \uDDDDD? signed 16 integers and replacement char
    return _charescape.sub(_replace, escaped).encode('ascii')


class Codec(codecs.Codec):
    def encode(self, input, errors='strict'):
        return rtfunicode_encode(input, errors), len(input)


class IncrementalEncoder(codecs.IncrementalEncoder):
    def encode(self, input, final=False):
        return rtfunicode_encode(input, self.errors)


class StreamWriter(Codec, codecs.StreamWriter):
    pass


def rtfunicode(name):
    if name == 'rtfunicode':
        return codecs.CodecInfo(
            name='rtfunicode',
            encode=Codec().encode,
            decode=Codec().decode,
            incrementalencoder=IncrementalEncoder,
            streamwriter=StreamWriter,
        )

codecs.register(rtfunicode)

Вместо кодирования "iso-8859-15" затем вы можете закодировать в «rtfunicode» вместо:

>>> u'\u20AC'.encode('rtfunicode') # EURO currency symbol
'\\u8364?'

Закодируйте любой текст, который вы вставляете в документ RTF, таким образом.

Обратите внимание, что он поддерживает только UCS-2 Unicode (\uxxxx, 2 байта), не UCS-4 (\Uxxxxxxxx, 4 байта);rtfunicode 1.1 поддерживает их, просто кодируя суррогатную пару UTF-16 в два\uDDDDD? целые числа со знаком.

@ MartijnPieters Хорошо, я думаю, это так.u"ü".encode('rtfunicode') работает с моим заголовком. Не знаю, что делает мои данные неверными, но я выясню это, спасибо!
спасибо ты решил мою проблему arpho
@ fabian789: да, это я. Я выпустилcode on PyPI as a package; Я не слышал о каких-либо проблемах до сих пор. Вы уверены, что ваши данные верны?
Спецификация rtf (1.9.1) явно упоминает суррогатные пары:"Surrogate pairs like \u-10187?\u-9138? must appear inside math object groups as in this example, or inside a math text-run group {\mr...} if not inside a math object." Хотя LibreOffice также понимает суррогатные пары без математического объекта.
эй, я похитил это, потому что мне нужна помощь, которая может у вас быть: я использую ваш код (или, скорее, материал изhere (Я думаю, что это в любом случае от вас ...)). Я сгенерировал какой-то RTF-файл с ним, но когда я его открываю, символы отключаются Может ли быть так, что мне нужно написать что-то относительно юникода в шапке? И нет, я не RTFM. Возможно я должен?

Похожие вопросы