1

在 Ubuntu 中运行的 Python 2.7 中,此代码:

f = open("testfile.txt", "w")
f.write("Line one".encode("utf-16"))
f.write(u"\r\n".encode("utf-16"))
f.write("Line two".encode("utf-16"))

在 Gedit 中读取时,在两行文本之间生成所需的换行符:

Line one
Line two

但是,在 Windows 7 中执行并在记事本中读取的相同代码会在“第一行”之后产生难以理解的字符,但记事本无法识别换行符。如何在 Windows 中为 UTF-16 编写正确的换行符以匹配我在 Ubuntu 中获得的输出?

我正在为仅读取 Unicode UTF-16 的仅 Windows 应用程序编写输出。我花了几个小时尝试不同的技巧,但似乎对记事本没有任何作用。值得一提的是,我可以在记事本中成功地将文本文件转换为 UTF-16,但我宁愿让脚本首先正确保存编码。

4

1 回答 1

8

问题是您以文本模式打开文件,但试图将其用作二进制文件。

这个:

u"\r\n".encode("utf-16")

… 编码为'\r\0\n\0'.

然后这个:

f.write('\r\0\n\0')

... 将 Unix 换行符转换为 Windows 换行符,给出'\r\0\r\n\0'.

当然,这会破坏您的 UTF-16 编码。除了这两个\r\n字节将解码为有效但未分配的代码点 U+0A0D 之外,这是一个奇数字节,这意味着你有一个剩余的\0. 因此,它不是L\0下一个字符,而是\0L、aka等等。

最重要的是,您可能正在为每个编码字符串编写一个新的 UTF-16 BOM。大多数 Windows 应用程序实际上会透明地处理并忽略它们,因此您实际上所做的只是浪费两个字节/行,但这实际上并不正确。


第一个问题的快速解决方法是以二进制模式打开文件:

f = open("testfile.txt", "wb")

这并不能解决多 BOM 问题,但可以解决损坏的\n问题。如果要修复 BOM 问题,可以使用有状态编码,或者为除第一次写入之外的所有写入明确指定'utf-16-le'(或)。'utf-16-be'


但是,对于这两个问题,简单的解决方法是使用模块(或者,对于较旧的 Python 2.x,模块)为您完成所有艰苦的工作:iocodecs

f = io.open("testfile.txt", "w", encoding="utf-8")
f.write("Line one")
f.write(u"\r\n")
f.write("Line two")
于 2013-06-18T01:20:59.107 回答