我有一个巨大的csv文件,大小超过250GB。我想替换角色"并且(没有。我觉得它应该非常简单,但文件大小确保没有编辑器打开文件。
我也可以使用python
来完成,可以使用以下代码:
with open(file) as src:
lines = src.read()
print(lines.replace(old_string, new_string))
但是这段代码要求文件在内存中。
一种选择是通过编写替换不需要的字符的行来创建另一个文件。但这意味着在磁盘上有两个文件,大小几乎相同。不幸的是,我在服务器上没有那么多的磁盘空间。
那么有没有办法覆盖行并替换字符而不创建新文件?
一些示例csv行是:
abc,"('91730', 'd9973')",1
def,"('91210', 'd9943')",1
ghi,"('91670', 'd9293')",1
答案 0 :(得分:0)
你可以像这样迭代文件的行:
with open(file, 'rt') as src:
for line in src:
print(line.replace('"', '').replace('(', ''))
但我会使用CSV module中的csvreader。
答案 1 :(得分:0)
作为创建第二个文件的折衷方案,您可以用空格替换所有有问题的字符。这样文件将保持相同的大小,不需要重写。 Python的translate()
函数执行速度很快:
import string
table = string.maketrans('(")', ' ')
block_size = 10000000
start_pos = 0
with open('input.csv', 'r+b') as f_input:
while True:
f_input.seek(start_pos)
block = f_input.read(block_size)
if len(block):
f_input.seek(start_pos)
f_input.write(block.translate(table))
else:
break
start_pos += block_size
这会给你一个输出文件,如:
abc, '91730', 'd9973' ,1
def, '91210', 'd9943' ,1
ghi, '91670', 'd9293' ,1
我建议您只处理文件"按原样#34;如果可能的话:
import csv
with open('input.csv', 'rb') as f_input:
for row in csv.reader(f_input):
data = re.match(r"\('(.*?)', '(.*?)'", row[1]).groups()
row[1] = data[0]
row.insert(1, data[1])
print row
对于您的数据,这将显示:
['abc', 'd9973', '91730', '1']
['def', 'd9943', '91210', '1']
['ghi', 'd9293', '91670', '1']
答案 2 :(得分:0)
如果您唯一的选择是编辑文件,则可以执行以下操作:
seek()
将第二个缓冲区写入同一个打开的文件。 (当然,只有新的大小,而不是完整的4096字节)因此,您必须跟踪2个文件位置:当前的read_buffer位置以及文件中的当前write_buffer位置,每次读取或写入时,都会重新定位文件指针。
这也可以在当时读取和写入一个字节,但我不知道(好)Python是如何缓冲数据的,所以它可能会更慢。
缓冲区的替代方法是使用内存映射。
我会提供一些示例代码,但我没有Python(我不太了解Python)。
但请确保先进行一些较小的测试,因为如果出现问题,您将无法获得原始文件的副本。
有关读取二进制文件的示例,请参阅this question。
答案 3 :(得分:0)
除非你使用64位版本的Python,否则我不会依赖seek
能够将指针放在2或4 Gb后面。我很确定它无法在Python 2 32位上运行,因为标准库文档说(强调我的):
file.seek(offset [,whence]): 设置文件的当前位置,,例如stdio&#fseek()。
在32位系统上,fseek只需要32位参数......无论如何,fseek
在Python 3中可能是安全的,因为整数是长整数,并且引用了stdio的fseek已从文档中删除 - 但我强烈建议您两次控制它...
所以我会尝试打开文件两次,一次在" rb"模式在其上有一个读指针,一旦在" r + b"模式,在其上有一个写指针。在这里它可能不起作用取决于操作系统,但许多允许单个进程在同一文件上获取多个文件描述符。对于Python2来说,代码与@ MartinEvans的答案没有什么不同:
table = string.maketrans('(")', ' ')
block_size = 10000000
start_pos = 0
with open('input.csv', 'rb') as f_input, open('input.csv', 'r+b') as f_output:
while True:
block = f_input.read(block_size)
if len(block):
f_input.seek(start_pos)
f_output.write(block.translate(table))
else:
break