如何在Python中将文本文件(包含非英语文本)的编码从"UTF-16 LE"转换为"UTF-8"?

How to convert encoding of text file (which contains text of language other than English) from "UTF-16 LE" to "UTF-8" in Python?

我的文件夹中几乎没有包含印地语文本的文本文件。但是那些文本文件是 UTF-16 LE 编码的。我想将编码更改为 UTF-8 而不更改其中的文本。我该怎么做?

我写了两个 python 文件,但其中 none 工作正常。当我 运行 它们中的任何一个时,随着编码的改变,它们会清除文件内容。这些是我的 Python 文件中的代码:

文件 1:

import os
for root, dirs, files in os.walk("."):  
    for filename in files:
        #print(filename[-4:])
        if(filename[-3:] == "txt"):
            f= open(filename,"w+")
            x = f.read()
            print(x)
            f.close()
            f1= open(filename, "w+", encoding="utf-8")
            f1.write(x)
            f1.close()

文件 2:

import codecs
BLOCKSIZE = 1048576
with codecs.open("ee.txt", "r", "utf-16-le") as sourceFile:
    with codecs.open("ee.txt", "w", "utf-8") as targetFile:
        while True:
            contents = sourceFile.read(BLOCKSIZE)
            print(contents)
            if not contents:
                break
            targetFile.write(contents)

在给你解释错了什么之前两个有用的提示:

我认为你应该删除打印件。它只会让你感到困惑,它取决于操作系统和环境,它会打印什么样的编码。

尝试使用一个非常短的文件(几个字符)并检查两个文件的输入和输出作为文本和字节。

现在解决方案:

关于第一个示例:您应该以已读方式打开第一个文件 (r)。

第二个例子:你打开同一个文件,第一步是读,但是在你读文件之前你打开它是为了写入,所以你截断了文件,你将没有字符可读。

使用ee.txt.tmp文件写入,最后如果没有错误,可以移动tmp文件去掉.tmp前缀。

一般来说:永远不要在同一个文件上读写。

您在读取内容时没有指定文件为 utf-16 LE - 那个,并且存在试图同时读取和写入同一文件的混淆,这是行不通的。

此外,除非您 运行 服务器中的此代码可能会通过向您发送一个非常大的文本文件来进行攻击尝试,否则您不应该担心文件大小,只需阅读所有文件内容即可立刻。 (为了让你有一个想法,圣经是一本大书,大小约为 3 MB(使用 8 位编码) - 即使是小型 VPS 服务器也将有大约 200MB 的可用内存到您的程序 - 也就是说,您可以一次转换一本 30 多本圣经大小的书)。典型的台式计算机的内存量是这个数量的几倍。

此外,相对较新的 "pathlib" Python 库可以轻松地遍历所有文本文件,其 Path.read_textPath.write_text 方法将打开一个文件,阅读或以正确的编码写入内容,并以单个表达式将其关闭。由于使用此方法时,在写入文件时读取已经完成,我们可以简单地通过两次调用来完成:

import pathlib
for filepath in pathlib.Path(".").glob("**/*.txt"):
   data = filepath.read_text(encoding="utf-16 LE")
   filepath.write_text(data, encoding="utf-8")

如果您希望安全起见,在文件转换过程中发生灾难性计算机崩溃的可能性很小,您可以写入一个不同名称的文件,然后执行 deleting/rename 之后 - 所以代码是这样的:

import pathlib
for filepath in pathlib.Path(".").glob("**/*.txt"):
   data = filepath.read_text(encoding="utf-16 LE")
   tmp_name = filepath.name + ".tmp"
   filepath.with_name(tmp_name).write_text(data, encoding="utf-8")
   filepath.unlink()
   filepath.with_name(tmp_name).rename(filepath.name)