UnicodeDecodeError: кодек «ascii» не может декодировать байт 0xe4 - PullRequest
0 голосов
/ 17 мая 2018

Мне интересно, может ли кто-нибудь мне помочь, я пробовал искать заранее, но не могу найти ответ:

У меня есть файл с именем info.dat, который содержит:

#
# *** Please be aware that the revision numbers on the control lines may not always
# *** be 1 more than the last file you received. There may have been additional
# *** increments in between.
#
$001,427,2018,04,26
#
# Save this file as info.dat
#

Я пытаюсь зациклить файл, получить номер версии и записать его в свой файл

with open('info.dat', 'r') as file:
    for line in file:
        if line.startswith('$001,'):
            with open('version.txt', 'w') as w:
                version = line[5:8] # Should be 427
                w.write(version + '\n')
                w.close()

Хотя это и дает правильную информацию, я получаю следующую ошибку:

Traceback (most recent call last):
File "~/Desktop/backup/test.py", line 4, in <module>
for line in file:
File "/usr/local/Cellar/python/3.6.5/Frameworks/Python.framework/Versions/3.6/lib/python3.6/encodings/ascii.py", line 26, in decode
return codecs.ascii_decode(input, self.errors)[0]
UnicodeDecodeError: 'ascii' codec can't decode byte 0xe4 in position 6281: ordinal not in range(128)

При попытке добавить следующее

with open('info.dat', 'r') as file:
    for line in file:
        if line.startswith('$001,'):
            with open('version.txt', 'w') as w:
                version = line[5:8]
                # w.write(version.encode('utf-8') + '\n')
                w.write(version.decode() + '\n')
                w.close()

Я получаю следующую ошибку

Traceback (most recent call last):
File "~/Desktop/backup/test.py", line 9, in <module>
w.write(version.encode('utf-8') + '\n')
TypeError: can't concat str to bytes

Ответы [ 2 ]

0 голосов
/ 17 мая 2018

Вы пытаетесь открыть текстовый файл, который будет неявно декодировать каждую строку с вашей кодировкой по умолчанию, затем вручную перекодировать каждую строку с помощью UTF-8, а затем записать его в текстовый файл, который будет неявно декодировать этот UTF-8 снова используя кодировку по умолчанию.Это не сработает.Но хорошая новость в том, что правильный намного проще сделать.


Если вы знаете, что входной файл находится в формате UTF-8 (что, вероятно, не…см. ниже), просто откройте файлы как UTF-8, а не как кодировку по умолчанию:

with open('info.dat', 'r', encoding='utf-8') as file:
    for line in file:
        if line.startswith('$001,'):
            with open('version.txt', 'w', encoding='utf-8') as w:
                version = line[5:8] # Should be 427
                w.write(version + '\n')
                w.close()

На самом деле, я уверен, что ваши файлы не в UTF-8, но Latin-1 (в Latin-1 \xa3 равен ä; в UTF-8 это начало 3-байтовой последовательности, которая, вероятно, кодирует символ CJK).Если это так, вы можете сделать то же самое с правильной кодировкой вместо неправильной, и теперь она будет работать.


Но если вы не знаете, что такое кодировка, не пытайтесьУгадай;просто придерживайтесь бинарного режима.Это означает передачу режимов rb и wb вместо r и w и использование литералов bytes:

with open('info.dat', 'rb') as file:
    for line in file:
        if line.startswith(b'$001,'):
            with open('version.txt', 'wb') as w:
                version = line[5:8] # Should be 427
                w.write(version + b'\n')
                w.close()

В любом случае, нет необходимости вызывать encodeили decode где угодно;просто позвольте файловым объектам позаботиться об этом за вас, и везде иметь дело только с одним типом (str или bytes).

0 голосов
/ 17 мая 2018

encode () возвращает байты, но '\ n' является строкой, вам нужно преобразовать строку в байтах, чтобы она была байтами + байтами, поэтому попробуйте это

w.write(version.encode('utf-8') + b'\n')
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...