2012-03-28 65 views
11

我遇到了一个问题,我没有看到任何人在StackOverflow遇到甚至谷歌的事情。Python不会读整个文本文件

我的主要目标是能够用另一个字符串替换文件中字符串的出现次数。有没有一种方法可以访问文件中的所有行。

问题是,当我尝试读取大文本文件(1-2 gb)的文本时,python只读取它的一个子集。

例如,我会做一个非常简单的命令,如:

newfile = open("newfile.txt","w") 
f = open("filename.txt","r") 
for line in f: 
    replaced = line.replace("string1", "string2") 
    newfile.write(replaced) 

而且只写原始文件的第一个382 MB。有没有人以前遇到过这个问题?

我尝试了一些不同的解决方案,如使用:

import fileinput 
for i, line in enumerate(fileinput.input("filename.txt", inplace=1) 
    sys.stdout.write(line.replace("string1", "string2") 

但它也有同样的效果。也不读取数据块文件,如使用

我已经将范围缩小到最有可能是在问题一读,而不是写问题,因为它发生了简单的打印出线条。我知道还有更多的线条。当我在Vim这样的全文本编辑器中打开它时,我可以看到最后一行应该是什么,并且它不是python打印的最后一行。

任何人都可以提供任何建议或尝试的东西吗?

我目前使用的是Windows XP的32位版本的RAM的3.25 GB和运行的Python 2.7

*编辑发现的解决方案(感谢Lattyware)。使用迭代

def read_in_chunks(file, chunk_size=1000): 
    while True: 
     data = file.read(chunk_size) 
     if not data: break 
     yield data 
+1

一行一行地读取迭代器应该是一个懒惰的操作,所以它应该工作,不管文件的大小。虽然它不应该影响你的情况,但是在打开文件时你也会想用''with'' - 这是一个很好的做法,而不是正确地处理异常情况下的关闭。 – 2012-03-28 10:49:25

+0

工作很好!非常感谢。 *编辑:我尝试在这里发布迭代器代码,但它不会格式化,所以我将它添加到原始文章中。 – user1297872 2012-03-28 11:08:39

+0

你用不同的大文本文件试过了吗?有没有382mb中的文件有些奇怪 - 一些奇怪的字符被视为文件的结尾? – neil 2012-03-28 11:13:40

回答

1

如果使用这样的文件:

with open("filename.txt") as f: 
    for line in f: 
     newfile.write(line.replace("string1", "string2")) 

它应该只在一个时间读入内存一条线,除非你保持在内存中该行的参考。
每行读完后,它将由python的垃圾收集器来摆脱它。试试这个,看看它是否适合你:)

22

尝试:

f = open("filename.txt", "rb") 

在Windows上,rb意味着以二进制模式打开的文件。根据文档,文本模式与二进制模式仅对行尾字符有影响。但是(如果我没有记错的话)我相信在Windows上以文本模式打开文件也会对EOF(十六进制1A)做些什么。

您也可以使用fileinput时指定的模式:

fileinput.input("filename.txt", inplace=1, mode="rb") 
+0

这也适用!我最喜欢这个解决方案,因为改变现有代码有多容易。 – user1297872 2012-03-28 11:20:42

+0

如何有“那也行得通”?这显然是你的问题。还有什么其他方法可以工作?嗯,我在评论中看到,指定要读取的字节长度,而不是使用“readline” – jsbueno 2012-03-28 12:27:14

+0

真棒,为我工作 – Stoyan 2014-04-21 10:43:17

2

你确定这个问题是阅读而不是用写出来? 您是否关闭了写入的文件,明确地为newfile.close()或使用with构造?

不关闭输出文件通常是在缓冲进行到某处时出现此类问题的根源。如果您的设置也是如此,关闭应该修复您的初始解决方案。