python - ultimos - Tratar con una cadena que contiene codificaciones de caracteres múltiples
python ultimos caracteres (5)
Aquí hay un ejemplo relativamente simple de cómo hacerlo ...
# -*- coding: utf-8 -*-
import re
# Test Data
ENCODING_RAW_DATA = (
(''latin_1'', ''L'', u''Hello''), # Latin 1
(''iso8859_2'', ''E'', u''dobrý večer''), # Central Europe
(''iso8859_9'', ''T'', u''İyi akşamlar''), # Turkish
(''iso8859_13'', ''B'', u''Į sveikatą!''), # Baltic
(''shift_jis'', ''J'', u''今日は''), # Japanese
(''iso8859_5'', ''C'', u''Здравствуйте''), # Cyrillic
(''iso8859_7'', ''G'', u''Γειά σου''), # Greek
)
CODE_TO_ENCODING = dict([(chr(ord(code)-64), encoding) for encoding, code, text in ENCODING_RAW_DATA])
EXPECTED_RESULT = u''''.join([line[2] for line in ENCODING_RAW_DATA])
ENCODED_DATA = ''''.join([chr(ord(code)-64) + text.encode(encoding) for encoding, code, text in ENCODING_RAW_DATA])
FIND_RE = re.compile(''[/x00-/x1A][^/x00-/x1A]*'')
def decode_single(bytes):
return bytes[1:].decode(CODE_TO_ENCODING[bytes[0]])
result = u''''.join([decode_single(bytes) for bytes in FIND_RE.findall(ENCODED_DATA)])
assert result==EXPECTED_RESULT, u"Expected %s, but got %s" % (EXPECTED_RESULT, result)
No estoy muy seguro de cómo hacer esta pregunta realmente, y no estoy cerca de encontrar una respuesta, así que espero que alguien pueda ayudarme.
Estoy escribiendo una aplicación de Python que se conecta a un host remoto y recibe datos de bytes posteriores, que desempaquetar utilizando el módulo de estructura integrado de Python. Mi problema es con las cadenas, ya que incluyen codificaciones de caracteres múltiples. Aquí hay un ejemplo de una cadena de este tipo:
"^ LT es un ejemplo ^ Gstring con múltiples codificaciones ^ Jcharacter"
Donde las diferentes codificaciones comienzan y terminan se marcan usando caracteres de escape especiales:
- ^ L - Latin1
- ^ E - Europa Central
- ^ T - turco
- ^ B - Báltico
- ^ J - japonés
- ^ C - cirílico
- ^ G - Griego
Y así sucesivamente ... Necesito una forma de convertir este tipo de cadena en Unicode, pero realmente no estoy seguro de cómo hacerlo. He leído sobre los códecs de Python y string.encode / decode, pero en realidad no soy más inteligente. Debo mencionar también que no tengo control sobre cómo el host genera las cadenas.
Espero que alguien me pueda ayudar a comenzar esto.
Definitivamente tiene que dividir la cadena primero en las subcadenas con diferentes codificaciones, y decodificarlas por separado. Solo por diversión, la obligatoria versión de "una línea":
import re
encs = {
''L'': ''latin1'',
''G'': ''iso8859-7'',
...
}
decoded = ''''.join(substr[2:].decode(encs[substr[1]])
for substr in re.findall(''/^[%s][^^]*'' % ''''.join(encs.keys()), st))
(no hay comprobación de errores, y también querrás decidir cómo manejar ''^'' caracteres en subcadenas)
Escribía un códec que escaneaba incrementalmente la cadena y decodificaba los bytes a medida que aparecían. Esencialmente, tendrías que separar las cadenas en fragmentos con una codificación consistente y decodificarlas y anexarlas a las cadenas que las siguieron.
No hay funcionalidad incorporada para decodificar una cadena como esta, ya que es realmente su propio códec personalizado. Simplemente necesita dividir la cadena en esos caracteres de control y decodificarla en consecuencia.
Aquí hay un ejemplo (muy lento) de una función tal que maneja latin1 y shift-JIS:
latin1 = "latin-1"
japanese = "Shift-JIS"
control_l = "/x0c"
control_j = "/n"
encodingMap = {
control_l: latin1,
control_j: japanese}
def funkyDecode(s, initialCodec=latin1):
output = u""
accum = ""
currentCodec = initialCodec
for ch in s:
if ch in encodingMap:
output += accum.decode(currentCodec)
currentCodec = encodingMap[ch]
accum = ""
else:
accum += ch
output += accum.decode(currentCodec)
return output
Una versión más rápida puede usar str.split o expresiones regulares.
(Además, como puede ver en este ejemplo, "^ J" es el carácter de control para "nueva línea", por lo que sus datos de entrada tendrán algunas restricciones interesantes.)
Supongo que no hay forma de convencer a la persona que aloja la otra máquina para que cambie a Unicode.
Esta es una de las razones por las que se inventó Unicode, después de todo.