Форум сайта python.su
0
Всем привет! Подскажите, пожалуйста, чем можно разрешить ситуацию: имеется файл, часть данных в нем содержится в кодировке UTF-16LE, другая часть вообще не текст. Части с текстом в нужной мне кодировке разбросаны по файлу без объявления начала и конца таких блоков. Есть ли в 3 питоне такое средство, чтобы декодировать только известные кодировке байты? Перебирать файл по 4 байта бессмысленно, так как позиции начала этих блоков не всегда кратны четырем. Пусть даже будет мусор, мне не важно.
Спасибо.
Офлайн
16
Если кириллицы нет, можно как вариант посимвольно проверять и отсеивать не ascii:
>>> def is_ascii(s): return all(ord(c) < 128 for c in s) >>> is_ascii('ô') False >>> is_ascii('t') True >>> is_ascii('в') False
Офлайн
16
Еще можно так:
import string def isAscii(s): if s in string.ascii_letters or s in string.digits or s in string.punctuation: return True return False for line in open('Connect.txt' , encoding='utf-16le'): st = '' for x in line: if isAscii(x): st += x print(st)
Отредактировано alexbadaloff (Апрель 17, 2013 13:36:21)
Прикреплённый файлы:
Connect.txt (392 байта)
Офлайн
0
Спасибо, alexbadaloff. Эх, а мне нужна кириллица 
Офлайн
16
evgen34
Спасибо, alexbadaloff. Эх, а мне нужна кириллица
import string def is_ascii(s): if (ord(s) > 31 and ord(s)<122 )or(ord(s) > 1039 and ord(s) < 1104): return True return False for line in open('test.txt', encoding='utf-16le'): st = '' for x in line: if is_ascii(x): st += x print(st)
Отредактировано alexbadaloff (Апрель 17, 2013 14:43:31)
Офлайн
0
alexbadaloffТакой вариант тоже не работает:import string def is_ascii(s): if (ord(s) > 31 and ord(s)<122 )or(ord(s) > 1039 and ord(s) < 1104): return True return False for line in open('test.txt', encoding='utf-16le'): st = '' for x in line: if is_ascii(x): st += x print(st)
UnicodeDecodeError: 'utf16' codec can't decode bytes in position 1362-1363: illegal UTF-16 surrogate
Офлайн
16
Тогда ждём более опытных.
Офлайн
0
Заметил, что блоки с текстом начинаются с четных байтов
Получилось извлечь первые читабельные тексты.
ffc = open(file,"rb"); data = ffc.read(); ffc.close text = str() i = 0 for x in range(int(len(data)/2)): try: text += data[i:i+2].decode('UTF-16LE') i += 2 except: i += 2 print(text)
Офлайн
173
При декодировании из байтов или при конструировании строки, можно передать параметр errors, который по умолчанию = ‘strict’, т.е. при любой ошибке вызывается исключение, но есть и другие.
http://docs.python.org/3.3/library/stdtypes.html#bytes.decode
>>> print(str(b'test\xfftest', 'utf-8')) Traceback (most recent call last): File "<stdin>", line 1, in <module> UnicodeDecodeError: 'utf-8' codec can't decode byte 0xff in position 4: invalid start byte >>> print(str(b'test\xfftest', 'utf-8', 'ignore')) testtest
Офлайн
0
reclosedev, спасибо!
В итоге получился такой код:
def is_ascii(s): if (ord(s) > 31 and ord(s)<122 )or(ord(s) > 1039 and ord(s) < 1104)or(ord(s) in (9,10,13)): return True return False file = open('in.some',"rb"); data = file.read(); file.close() text = str() texttemp = data.decode('UTF-16LE', 'ignore') for i in texttemp: if is_ascii(i) == True: text += i file = open('out.txt',"wb"); data = file.write(text.encode()); file.close()

Офлайн