我有一个文件夹,其中包含需要修改的文件,以便以真实格式提取真实文件。
我需要从文件的开头和结尾删除一定数量的字节,以便提取我正在寻找的数据。
我怎么能在python中这样做?
我非常感谢您提供的任何帮助或指导。
答案 0 :(得分:1)
所以,基础逻辑:
答案 1 :(得分:0)
您的问题构造得非常糟糕,但由于这是一些高级内容,我会为您提供代码。
现在可以使用os.walk()递归遍历所需的目录并应用我的slicefile()函数。
此代码执行以下操作:
检查开始和结束参数的有效性后,它会在打开的文件上创建一个内存映射。 mmap()创建一个内存映射对象,在这种情况下,mapps是写入文件的文件系统的一部分。该对象使用一些其他方法(如move())公开类似字符串和类文件的接口。因此,您可以将内存映射视为字符串或文件,或使用size(),move(),resize()或您需要的任何其他方法。
我们计算起点和终点之间的距离,即这是我们到底有多少字节。
我们移动字节流,从最开始位置开始,从开始位置开始到0位置,即我们向后移动它们以获得起始点指示的字节数。
我们丢弃文件的其余部分。即我们将其调整为最终起始字节。那么,剩下的就是我们的新字符串。
文件越大,操作时间越长。不幸的是,你无能为力。如果文件很大,这是你最好的选择。该过程与从内存数组的开始/中间删除项目时的过程相同,除了必须缓冲(以块为单位)不要过多填充RAM。
如果您的文件小于可用RAM空间的三分之一,则可以将其整个加载到带有f.read()的字符串中,然后对加载的内容执行字符串切片(s = s [start:end])然后通过再次打开并将其写回f.write(s)将其写回文件。 如果您有足够的磁盘空间,则可以打开另一个文件,在原始文件中寻找所需的起始点,然后以块的形式读取它并将它们写入新文件。甚至可能使用shutil.copyfileobj()。之后,删除原始文件并使用os.rename()将新文件放在其位置。这些是您唯一的3个选项。 整个文件放入RAM;通过向后缓冲然后调整大小来移动;并且,复制到另一个文件,然后重命名它。第二种选择是最普遍的,并且对于小文件或大文件都不会失败。因此我用它。
好的,不仅有3个选项。还有第四种选择。通过使用低级操作操纵文件系统本身,可以从文件的开头切断N个字节。编写一种截断开头而不是结尾的truncate()函数。但这将是非常自杀的。最终会出现内存碎片,并且会出现整个混乱。无论如何,你还不需要这样的速度。在脚本完成之前,您将一直耐心等待。 :d
为什么我使用mmap()?
因为它使用在OS中实现的内存映射而不是全新的代码。这减少了处理打开文件所需的系统调用次数。一半的工作都是在操作系统上进行的,让Python可以轻松呼吸。
因为它主要是用C语言编写的,所以它比纯Python实现更快。
因为它实现了我们需要的move()。缓冲和一切都已经写好了,因此不需要庞大的while循环,这将是替代(手动)解决方案。
等等......
from mmap import mmap
def slicefile (path, start=0, end=None):
f = open(path, "r+b") # Read and write binary
f.seek(0, 2)
size = f.tell()
start = 0 if start==None else start
end = size if end==None else end
start = size+start if start<0 else start
end = size+end if end<0 else end
end = size if end>size else end
if (end==size and start==0) or (end<=start):
f.close()
return
# If start is 0, no need to move anything, just cut off the rest after end
if start==0:
f.seek(end)
f.truncate()
f.close()
return
# Modify in place using mapped memory:
newsize = end-start
m = mmap(f.fileno(), 0)
m.move(0, start, newsize)
m.flush()
m.resize(newsize)
m.close()
f.close()