"utf-8"编解码器无法解码字节 - Python

3

我的 Django 应用程序可以处理 .txt.doc 文件类型。应用程序会打开文件,将其与数据库中的其他文件进行比较,并输出一些报告。

现在的问题是,当文件类型为 .txt 时,我会收到 'utf-8' codec can't decode byte 错误(在这里我使用了 encoding='utf-8')。当我将 encoding='utf-8' 更改为 encoding='ISO-8859-1' 时,错误会变成 'latin-1' codec can't decode byte

我想找到适用于所有文件类型的编码格式。 这是我的函数的一小部分:

views.py:

@login_required(login_url='sign_in')
def result(request):
    last_uploaded = OriginalDocument.objects.latest('id')
    original = open(str(last_uploaded.document), 'r', encoding='utf-8')
    original_words = original.read().lower().split()
    words_count = len(original_words)
    open_original = open(str(last_uploaded.document), "r")
    read_original = open_original.read()
    report_fives = open("static/report_documents/" + str(last_uploaded.student_name) + 
    "-" + str(last_uploaded.document_title) + "-5.txt", 'w')
    # Path to the documents with which original doc is comparing
    path = 'static/other_documents/doc*.txt'
    files = glob.glob(path)

    rows, found_count, fives_count, rounded_percentage_five, percentage_for_chart_five, fives_for_report, founded_docs_for_report = search_by_five(last_uploaded, 5, original_words, report_fives, files)

    context = {
      ...
    }

    return render(request, 'result.html', context)

2
我想找到一种编码格式,可以适用于所有类型的文件。-> 没有通用的编码方式可以自动知道如何解码特定编码的已编码文件。UTF-8是一个很好的选择,与其他编码具有许多兼容性。您可以简单地忽略或替换无法解码的字符,例如:open(<your_file>, encoding="utf-8", errors="ignore") 或 (errors="replace")。也许这可以帮助你?! - colidyre
1
你是如何读取doc文件的?您使用任何库吗?文件打开不支持doc格式。 - Harsh Nagarkar
@BobReynolds 你所说的“安全”是指程序不会引发解码错误吗?那么,是的——因为你没有使用errors="strict" - colidyre
@colidyre,我为什么会问这个问题呢?因为我的应用程序将doc文件显示为其他类型的文件。我以为可能是因为错误关键字导致的。但是,没有一个能解决这个问题。 - Bob Reynolds
啊,好的,我明白了。我已经更新了我的回答。@BobReynolds - colidyre
显示剩余3条评论
1个回答

3

没有一种通用的编码方式可以自动地知道如何解码特定编码的已编码文件。

UTF-8是一个与其他编码兼容性很好的选择。例如,您可以像这样简单地忽略或替换无法解码的字符:ignorereplace

from codecs import open
original = open(str(last_uploaded.document), encoding="utf-8", errors="ignore")
original_words = original.read().lower().split()
...
original.close()

甚至可以使用上下文管理器(with语句),让其自动关闭文件:

with open(str(last_uploaded.document), encoding="utf-8", errors="ignore") as fr:
    original_words = fr.read().lower().split()
    ...

(注:如果您使用的是Python 3,则无需使用 codecs 库,但您已经标记了您的问题与 python-2.7 。)
您可以在此处查看使用不同错误处理程序的优缺点herehere。必须知道,不使用错误处理程序将默认使用 errors =“strict”,这可能不是您想要的。其他选项可能几乎是自说明的,例如:
  • 使用 errors ="replace"将使用适当的替换标记替换无法解码的字符
  • 使用 errors ="ignore"将仅忽略该字符并继续读取文件数据。
应根据您的需求和用例使用适当的选项。
您说您不仅遇到了纯文本文件的编码问题,还遇到了专有的 doc 文件:
因为许多信息以二进制格式存储,所以 .doc 格式不是您可以简单使用 open()或 codecs.open()读取的纯文本文件,请参见更多详细信息此站点。因此,您需要使用特殊的 .doc 文件阅读器从中获取文本。您使用哪个库取决于您的Python版本,也可能取决于您使用的操作系统。这里可能是您的起点。
不幸的是,即使使用库,也无法完全防止编码错误。 (也许可以,但我不确定编码是否像在 .docx 文件中一样保存在文件本身。)您还有机会找出文件的编码方式。如何处理编码错误可能取决于库本身。
因此,我只是猜测您正尝试将 .doc 文件打开为简单的文本文件。因此,您将收到解码错误,因为它未保存为可读文本。即使您摆脱了错误,您也只能看到非可读文本:(我已经创建了一个具有LibreOffice的简单文本文件以 doc 格式(Microsoft Word 1997-2003)):
In [1]: open("./test.doc", "r").read()
UnicodeDecodeError: 'utf-8' codec can`t decode byte 0xd0 in position 0: invalid continuation byte

In [2]: open("./test.doc", "r", errors="replace").read()  # or open("./test.doc", "rb").read()
'��\x11\u0871\x1a�\x00\x00\x00' ...

非常感谢,朋友。现在我有一些可以尝试的方法。但是我认为在2020年阅读doc文件不应该是一件难事,但我们能做什么呢。 - Bob Reynolds
先生,您好,祝您有个愉快的一天。您能帮我看一下这个问题吗:https://stackoverflow.com/questions/61156491/django-form-save-is-not-creating-modelform ?最近几天我的问题没有得到很多人的关注,也无法标记某些人。请您帮帮我。谢谢。 - Bob Reynolds

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接