使用Python替换二进制文件中的"\r\r\n"为"\r\n"

4

我对Python非常陌生,刚开始学习并尝试通过它来完成任务,希望得到一些帮助(使用Python 3.1)。

我使用“excel”方言的DictWriter写了一个CSV文件。在创建文件后,我注意到文件中有额外的行,并且经过仔细检查,发现每行末尾都是"\r\r\n"而不是"\r\n"。

我可以通过以下两种方式之一解决这个问题:

  1. 以二进制模式打开文件而不是文本模式。但问题在于我无论如何都无法让writerow()针对二进制文件工作——我得到了大量的异常。

  2. 第二个(更简单)的解决方法只是将所有的"\r\r\n"替换为"\r\n"。

然而,在我的尝试中,我遇到了以下错误:

a. 没有先关闭文件,搜索和替换只会添加更多的"\r\r\n"行。 b. 我已经尝试过先关闭文件,然后以二进制模式重新打开并进行相同的搜索和替换,但我得到了一个错误:

WindowsError: [Error 32] 因为正在被另一个进程使用,所以无法访问该文件

以下是代码:

#code before this writes to the final in text mode
myfile.close()
myfile = open(outputFile, "wb")
for line in fileinput.FileInput(outputFile, inplace=1):
    line = line.replace("\r\r\n", "\r\n")
    print (line)
myfile.close()

感谢任何人可以提供的帮助!

旁注:发生这种情况的原因是您没有使用 newline='' 调用 .csv 文件的 open(这是使用 csv 模块打开文件的唯一正确方式),而且您正在使用 Windows 并使用类似于 Windows 的 csv 方言。csv.writer 显式地写入了 \r\n(因为该方言使用 \r\n 作为换行符),并且由于未在 open 中使用 newline='' 禁用行结束转换,因此 io.TextIOWrapper\n 转换为 \r\n,使其在磁盘上变成了 \r\r\n - ShadowRanger
5个回答

5
安全地修改文件的方法(除了可以安全地进行追加之外)是将其带有修改的副本复制到新文件中,删除旧文件,将新文件重命名为旧文件的名称。这是避免灾难性错误和数据丢失的一种可靠方法。根据平台,“删除旧文件,重命名新文件”步骤可能是原子的,但在Windows中很难实现,并不是那么关键。
因此,我会简单地这样做 - 一口气完成,除非文件非常大(超过1GB):
with open(filename, 'rb') as f:
  data = f.read()
with open(newfilename, 'wb') as f:
  f.write(data.replace('\r\r\n', '\r\n'))
os.unlink(filename)
os.rename(newfilename, filename)

你的代码问题在于二进制和文本模式的混淆 -- 例如,你无法从以二进制模式打开的文件中正确地“读取一行”。
在Python 3.1中,我们需要处理“字节”实例,而不是字符串,因为文件是二进制的。因此,根据文档write调用必须更改。
  f.write(data.replace(b'\r\r\n', b'\r\n'))

那些以b为前缀的表示我们正在处理bytes而不是str

我刚试了一下,但是出现了这个错误:"TypeError: expected an object with the buffer interface",在这一行代码上:"f.write(data.replace('\r\r\n', '\r\n'))"。 - TMC
@TMC,你应该提到你正在使用Python3 ;) - John La Rooy
啊,Python 3.1——我刚刚在你的问题中注意到它(有一个特定的标签,因为在几乎每个人都使用的2.5/2.6和更新的3.1之间,正确的答案差别很大)。解决方案在这里:http://docs.python.org/3.1/library/stdtypes.html#bytes-and-byte-array-methods——让我编辑答案以澄清。 - Alex Martelli
@gnibbler,在第一段末尾括号里他确实做了,只是没有引起我的注意(最好作为标记;-)。我已经编辑了答案以显示 Python 3 所需的微小更改。 - Alex Martelli

1

0

试试这个:

fileR = open(outputFile, "r")
text = fileR.read().replace("\r\r\n", "\r\n")
fileR.close()
fileW = open(outputFile, "wb")
fileW.write(text)
fileW.close()

这个也不行。第二次以二进制文件(“b”标志)打开文件时,当我尝试写出新文本时,会出现以下错误:“TypeError:必须是字节或缓冲区,而不是字符串”。我尝试了不使用二进制标志(因此将其作为文本打开),但我仍然遇到同样的问题。每一行都用\r\r\n而不是\r\n写出。 - TMC

0

我对文件处理中的特殊情况并不是很熟悉。但是,既然你提到你正在处理一个CSV文件(可以用Excel打开),我建议你瞥一眼pyExcelerator

希望这可以帮到你。


有用的库很方便,但对我来说现在有点过头了。我已经正确地编写了CSV文件,并且可以轻松地导入到Excel中。 - TMC

0

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