Я работаю над приложением Python 3 Tkinter (ОС - Windows 10), общая функциональность которого включает в себя следующие детали:
Чтение ряда текстовых файлов, которые могут содержать данные вascii, cp1252, utf-8 или любая другая кодировка
Отображение содержимого любого из этих файлов в «окне предварительного просмотра» (виджет Tkinter Label).
Запись содержимого файла в один выходной файл (открытие для добавления каждый раз)
Для # 1: я сделал файл независимым от кодировки, простооткрытие и чтение файлов в двоичном режиме.Чтобы преобразовать данные в строку, я использую цикл, который проходит через список «вероятных» кодировок и пробует каждую из них по очереди (с error='strict'
), пока не достигнет той, которая не выдает исключение.Это работает.
Для # 2: Получив декодированную строку, я просто вызываю метод set()
для метки Tkinter textvariable
.Это также работает.
Для # 3: я открываю выходной файл обычным способом и вызываю метод write()
для записи декодированной строки.Это работает, когда строка была декодирована как ascii или cp1252, но когда она декодируется как utf-8, она выдает исключение:
'charmap' codec can't encode characters in position 0-3: character maps to <undefined>
Я искал вокруг и нашел довольно похожие вопросы, но ничего, что, кажется, не решаетэто конкретная проблема.Некоторые дополнительные сложности, которые ограничивают решения, которые будут работать для меня:
A.Я могу обойти эту проблему, просто оставив считанные данные в виде байтов и открыв / записав выходной файл в двоичном виде, но это делает некоторые из содержимого входного файла нечитаемыми.
B.Хотя это приложение в основном предназначено для Python 3, я пытаюсь сделать его кросс-совместимым с Python 2 - у нас есть некоторые медленные / поздние пользователи, которые будут его использовать.(Кстати, когда я запускаю приложение на Python 2, оно также генерирует исключения, но делает это как для данных cp1252, так и для данных utf-8.)
Для иллюстрации проблемы яМы создали этот урезанный тестовый скрипт.(Мое настоящее приложение - гораздо более крупный проект, и оно также является собственностью моей компании, поэтому оно не публикуется публично!)
import tkinter as tk
import codecs
#Root window
root = tk.Tk()
#Widgets
ctrlViewFile1 = tk.StringVar()
ctrlViewFile2 = tk.StringVar()
ctrlViewFile3 = tk.StringVar()
lblViewFile1 = tk.Label(root, relief=tk.SUNKEN,
justify=tk.LEFT, anchor=tk.NW,
width=10, height=3,
textvariable=ctrlViewFile1)
lblViewFile2 = tk.Label(root, relief=tk.SUNKEN,
justify=tk.LEFT, anchor=tk.NW,
width=10, height=3,
textvariable=ctrlViewFile2)
lblViewFile3 = tk.Label(root, relief=tk.SUNKEN,
justify=tk.LEFT, anchor=tk.NW,
width=10, height=3,
textvariable=ctrlViewFile3)
#Layout
lblViewFile1.grid(row=0,column=0,padx=5,pady=5)
lblViewFile2.grid(row=1,column=0,padx=5,pady=5)
lblViewFile3.grid(row=2,column=0,padx=5,pady=5)
#Bytes read from "files" (ascii Az5, cp1252 European letters/punctuation, utf-8 Mandarin characters)
inBytes1 = b'\x41\x7a\x35'
inBytes2 = b'\xe0\xbf\xf6'
inBytes3 = b'\xef\xbb\xbf\xe6\x9c\xa8\xe5\x85\xb0\xe8\xbe\x9e'
#Decode
outString1 = codecs.decode(inBytes1,'ascii','strict')
outString2 = codecs.decode(inBytes2,'cp1252','strict')
outString3 = codecs.decode(inBytes3,'utf_8','strict')
#Assign stringvars
ctrlViewFile1.set(outString1)
ctrlViewFile2.set(outString2)
ctrlViewFile3.set(outString3)
#Write output files
try:
with open('out1.txt','w') as outFile:
outFile.write(outString1)
except Exception as e:
print(inBytes1)
print(str(e))
try:
with open('out2.txt','w') as outFile:
outFile.write(outString2)
except Exception as e:
print(inBytes2)
print(str(e))
try:
with open('out3.txt','w') as outFile:
outFile.write(outString3)
except Exception as e:
print(inBytes3)
print(str(e))
#Start GUI
tk.mainloop()