我为我编写的程序编写了3个单独的测试用例。不幸的是,我填写了我的硬盘驱动器,也许大约300 GB。我想从每个测试用例文件中取样,然后删除文件的其余部分。
我知道如何在不使用" readline"的情况下读取在不使用内存的情况线,从而释放存储空间。
这是否可以使用Python库?
编辑:取出sed
,它创建一个临时文件
我想从每个测试用例文件中取样,然后删除文件的其余部分。
从顶部逐行读取行。写您要保留在文件开头的文章。将当前偏移量保持在文件中的结尾以及未读部件开始的位置。
如果复制的一块可能与目的地重叠;使用类似于memmove(fp+current_offset, fp+unread_offset, count)
的算法:"从缓冲区的开头复制字节" 。副本之后:
current_offset += count
unread_offset += count
继续直到采集足够的样品,然后致电file.truncate(current_offset)
在文件中的样本后删除所有内容。
例如,如果您想随机保留一半的行:
#!/usr/bin/env python
import random
with open('big-big.file', 'r+b') as file:
current_offset = file.tell()
while True:
line = file.readline() # b'n'-separated lines
if not line: # EOF
break
if random.random() < 0.5: # keep the line
unread_offset = file.tell()
file.seek(current_offset)
file.write(line)
current_offset = file.tell()
file.seek(unread_offset)
file.truncate(current_offset)
这是一种尝试使用mmap
重写的文件。我不想填充我的硬盘驱动器,所以没有测试任何大型。它是一个可运行的例子,但是您需要将这些东西刻在我用于测试的前后。
这将文件的前50%写入新文件,然后将其修剪。不知道这是否是您想要的顺序!
import mmap
import shutil
import os
from glob import glob
files_to_trim = 'deleteme*'
fraction_to_keep = .5
blocksize = 128*1024
# make test file
open('deleteme1', 'w').writelines('all work and no play {}n'.format(i)
for i in range(6))
open('deleteme2', 'w').writelines('all work and no play {}n'.format(i)
for i in range(10,18))
with open('output', 'wb') as out:
for filename in sorted(glob(files_to_trim)):
st_size = os.stat(filename).st_size
sample_size = int(st_size * fraction_to_keep)
with open(filename, 'r+b') as infile:
memfile = mmap.mmap(infile.fileno(), 0)
# find next line ending
need_newline = False
count = memfile.find(b'n', sample_size)
if count >= 0:
count += 1 # account for n
else:
count = st_size
need_newline = memfile[-1] == 'n'
# copy blocks to outfile
for rpos in range(0, count+blocksize-1, blocksize):
out.write(memfile[rpos:min(rpos+blocksize, count)])
if need_newline:
out.write('n')
# trim infile
remaining = st_size - count
memfile[:remaining] = memfile[count:]
memfile.flush()
memfile.close()
infile.truncate(remaining)
infile.flush()
# validate test file
print('deleteme1:')
print(open('deleteme1').read())
print('deleteme2:')
print(open('deleteme2').read())
print('output:')
print(open('output').read())