Уведомления

Группа в Telegram: @pythonsu

#1 Май 14, 2010 12:11:52

UsCr
От:
Зарегистрирован: 2009-11-04
Сообщения: 216
Репутация: +  0  -
Профиль   Отправить e-mail  

Определить кодировку файла.

Daevaorn
Вам уже целый тред пытаются объяснить, что нет такой кодировки – “уникод”
ОК.
Есть юникод. Это общее название для УТФ-8, ~-16, ~-32. Так верно?

ascii, ср1251, ср1252, … Это не уникод, правильно?

chardet не однозначен:
если кормить его первым (нулевым) элементом списка readlines, то он говорит что это “UTF-16LE”
если дать ему любой другой элемент списка, то это “ascii”

Если все элементы списка слепить в строку и скормить chardet'у, то это опять “UTF-16LE”.



Офлайн

#2 Май 14, 2010 12:27:25

PooH
От:
Зарегистрирован: 2006-12-05
Сообщения: 1948
Репутация: +  72  -
Профиль   Отправить e-mail  

Определить кодировку файла.

UsCr
Daevaorn
Вам уже целый тред пытаются объяснить, что нет такой кодировки – “уникод”
ОК.
Есть юникод. Это общее название для УТФ-8, ~-16, ~-32. Так верно?
Неверно. unicode - это набор символов. Все остальное - способы кодирования этого набора.

UsCr
chardet не однозначен:
если кормить его первым (нулевым) элементом списка readlines, то он говорит что это “UTF-16LE”
если дать ему любой другой элемент списка, то это “ascii”

Если все элементы списка слепить в строку и скормить chardet'у, то это опять “UTF-16LE”.
Вот и кормите его целиком строкой. Вот я вам покажу символ ‘\x46’(F) - вы скажите какая это кодировка? Это может быть ascii, UTF-8 или cp1251.
В данном случае первый байт нулевого элемента или целой строки лежит в характерном для UTF-16LE диапазоне.



Вот здесь один из первых отарков съел лаборанта. Это был такой умный отарк, что понимал даже теорию относительности. Он разговаривал с лаборантом, а потом бросился на него и загрыз…

Офлайн

#3 Май 14, 2010 13:52:56

UsCr
От:
Зарегистрирован: 2009-11-04
Сообщения: 216
Репутация: +  0  -
Профиль   Отправить e-mail  

Определить кодировку файла.

Сделал так.

# -*- coding: utf8 -*-

import os
import chardet

PATH = 'D:\\regfiles_test\\'
FILE = 'reg'

for i in [filelist for filelist in os.listdir(PATH) if filelist[-3:] == FILE]:

print i
source = open(PATH+i)
receiver = open(PATH+'deleter_'+i, 'w')
data = source.readlines()
code = chardet.detect(''.join(data))['encoding']
for ii in data:
j = ii.decode(code)
if j[0] == '[':
receiver.write('-'+j.encode('utf8'))
else:
receiver.write(j.encode('utf8'))
source.close()
receiver.close()
Вывалился вот так:
Traceback (most recent call last):
File "<pyshell#25>", line 1, in <module>
import unreg
File "C:\Python26\lib\unreg.py", line 18, in <module>
j = ii.decode(code)
File "C:\Python26\lib\encodings\utf_16_le.py", line 16, in decode
return codecs.utf_16_le_decode(input, errors, True)
UnicodeDecodeError: 'utf16' codec can't decode byte 0x0a in position 76: truncated data



Офлайн

#4 Май 14, 2010 14:19:25

Александр Кошелев
От: Москва
Зарегистрирован: 2007-02-03
Сообщения: 1724
Репутация: +  2  -
Профиль   Отправить e-mail  

Определить кодировку файла.

Тут вы попали в классическую ловушку. Вы открыли файл и прочитали из него строки. Но в зависомости от кодировки символ разделения строки может иметь различную длину, что обычный open не обрабатывает (проще говоря, он расчитывает на ascii).

Вам надо делать в такой последовательности:

* Открыть и прочесть файл целиком
* Определить кодировку
* Воспользоваться codecs.open и открыть файл ещё раз, указав кодировку
* И уже потом читать построчно



Офлайн

#5 Май 17, 2010 11:33:20

UsCr
От:
Зарегистрирован: 2009-11-04
Сообщения: 216
Репутация: +  0  -
Профиль   Отправить e-mail  

Определить кодировку файла.

Daevaorn
* Открыть и прочесть файл целиком
* Определить кодировку
* Воспользоваться codecs.open и открыть файл ещё раз, указав кодировку
* И уже потом читать построчно
# -*- coding: utf8 -*-

import os
import chardet
import codecs


PATH = 'D:\\regfiles_test\\'
FILE = 'reg'

def code_detecter(filename):
if type(filename) != type(''):
filename = str(filename)
with open(filename) as codefile:
data = codefile.readlines()

return chardet.detect(''.join(data))['encoding']

for i in [filelist for filelist in os.listdir(PATH) if filelist.endswith(FILE)]:
print i
code = code_detecter(PATH+i) #определяем кодировку исходного файла
source = codecs.open(PATH+i, 'r', code)
receiver = open(PATH+'deleter_'+i, 'w')

for ii in source.readlines():
j = ii.decode(code)
if j[0] == '[':
receiver.write('-'+j.encode('utf8'))
else:
receiver.write(j.encode('utf8'))
source.close()
receiver.close()
Теперь так:
Traceback (most recent call last):
File "<pyshell#27>", line 1, in <module>
import unreg
File "C:\Python26\lib\unreg.py", line 26, in <module>
j = ii.decode(code)
File "C:\Python26\lib\encodings\utf_16_le.py", line 16, in decode
return codecs.utf_16_le_decode(input, errors, True)
UnicodeEncodeError: 'ascii' codec can't encode character u'\ufeff' in position 0: ordinal not in range(128)
Хотя вы писали
Daevaorn
* И уже потом читать построчно
Это действительно имеет значение? Всмысле имеет значение читаю ли я файл посторочно или делаю .readlines()?



Отредактировано (Май 17, 2010 11:35:17)

Офлайн

#6 Май 17, 2010 23:07:25

Александр Кошелев
От: Москва
Зарегистрирован: 2007-02-03
Сообщения: 1724
Репутация: +  2  -
Профиль   Отправить e-mail  

Определить кодировку файла.

UsCr
j = ii.decode(code)
Читайте документцию по codecs.open, ссылку на которую я дал в прошлый раз. Там написано, что операции возращают уже уникод. Его не надо ещё раз пытаться декодировать.

Потом, вы как-то очень странно читаете “весь файл”, достаточно:
codefile.read()
Зачем вы читатет строчки и потом их соединяете?
UsCr
Всмысле имеет значение читаю ли я файл посторочно или делаю .readlines()?
Это почти одно и тоже, только readlines читает все строки файла сразу.



Офлайн

#7 Май 24, 2010 14:03:22

UsCr
От:
Зарегистрирован: 2009-11-04
Сообщения: 216
Репутация: +  0  -
Профиль   Отправить e-mail  

Определить кодировку файла.

Да, спасибо. Так работает:

# -*- coding: utf8 -*-

import os
import chardet
import codecs


PATH = 'D:\\regfiles_test\\'
FILE = 'reg'

def code_detecter(filename):

with open(filename) as codefile:
data = codefile.read()

return chardet.detect(data)['encoding']

for i in [filelist for filelist in os.listdir(PATH) if filelist.endswith(FILE)]:

print i
code = code_detecter(PATH+i) #определяем кодировку исходного файла
source = codecs.open(PATH+i, 'r', code)
receiver = open(PATH+'deleter_'+i, 'w')

for j in source.readlines():

if j[0] == '[':
receiver.write('-'+j.encode('utf8'))
else:
receiver.write(j.encode('utf8'))
source.close()
receiver.close()



Отредактировано (Май 24, 2010 14:24:48)

Офлайн

Board footer

Модераторировать

Powered by DjangoBB

Lo-Fi Version