Найти - Пользователи
Полная версия: Как декодировать только известные кодировке байты
Начало » Python для новичков » Как декодировать только известные кодировке байты
1
evgen34
Всем привет! Подскажите, пожалуйста, чем можно разрешить ситуацию: имеется файл, часть данных в нем содержится в кодировке UTF-16LE, другая часть вообще не текст. Части с текстом в нужной мне кодировке разбросаны по файлу без объявления начала и конца таких блоков. Есть ли в 3 питоне такое средство, чтобы декодировать только известные кодировке байты? Перебирать файл по 4 байта бессмысленно, так как позиции начала этих блоков не всегда кратны четырем. Пусть даже будет мусор, мне не важно.
Спасибо.
alexbadaloff
Если кириллицы нет, можно как вариант посимвольно проверять и отсеивать не ascii:

>>> def is_ascii(s):
    return all(ord(c) < 128 for c in s)
>>> is_ascii('ô')
False
>>> is_ascii('t')
True
>>> is_ascii('в')
False
alexbadaloff
Еще можно так:

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)

Пример файла из недавней темы приложил. Кириллица тоже тут не катит.
evgen34
Спасибо, alexbadaloff. Эх, а мне нужна кириллица
alexbadaloff
evgen34
Спасибо, alexbadaloff. Эх, а мне нужна кириллица

Вот. Если нужна utf-16le кодировка и кириллица:
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)

Если оно, подкинь репутации. А то как-то грустно у меня с этим.
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)
Такой вариант тоже не работает:
UnicodeDecodeError: 'utf16' codec can't decode bytes in position 1362-1363: illegal UTF-16 surrogate
alexbadaloff
Тогда ждём более опытных.
evgen34
Заметил, что блоки с текстом начинаются с четных байтов Получилось извлечь первые читабельные тексты.
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)
alexbadaloff, благодарю за помощь.
reclosedev
При декодировании из байтов или при конструировании строки, можно передать параметр 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
evgen34
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()
На выходе получается текстовый файлик, в котором не так много мусора, разобраться можно
This is a "lo-fi" version of our main content. To view the full version with more information, formatting and images, please click here.
Powered by DjangoBB