如何使用python从文件的开头和结尾删除特定数量的字节?

时间:2017-10-14 09:25:34

标签: python recursion extract extraction

我有一个文件夹,其中包含需要修改的文件,以便以真实格式提取真实文件。

我需要从文件的开头和结尾删除一定数量的字节,以便提取我正在寻找的数据。

我怎么能在python中这样做?

  • 我只需要在整个文件夹上递归工作
  • 我还需要输出(或修改现有的)文件并删除字节。

我非常感谢您提供的任何帮助或指导。

2 个答案:

答案 0 :(得分:1)

  1. 对文件os.walk
  2. 的递归迭代
  3. 更改档案中的位置:f.seek
  4. 获取文件大小:os.stat
  5. 将数据从当前位置移至文件末尾:f.truncate
  6. 所以,基础逻辑:

    1. 迭代文件
    2. 获取文件大小。
    3. 打开文件(' rb +'我支持)
    4. 从您想要阅读文件的位置寻找位置
    5. 读取要删除的字节数(f.read(file_size - top_dropped - bottom_dropped))
    6. SEEK(0)
    7. 将阅读文字写入文件
    8. 截断文件

答案 1 :(得分:0)

您的问题构造得非常糟糕,但由于这是一些高级内容,我会为您提供代码。

现在可以使用os.walk()递归遍历所需的目录并应用我的slicefile()函数。

此代码执行以下操作:

  1. 检查开始和结束参数的有效性后,它会在打开的文件上创建一个内存映射。 mmap()创建一个内存映射对象,在这种情况下,mapps是写入文件的文件系统的一部分。该对象使用一些其他方法(如move())公开类似字符串和类文件的接口。因此,您可以将内存映射视为字符串或文件,或使用size(),move(),resize()或您需要的任何其他方法。

  2. 我们计算起点和终点之间的距离,即这是我们到底有多少字节。

  3. 我们移动字节流,从最开始位置开始,从开始位置开始到0位置,即我们向后移动它们以获得起始点指示的字节数。

  4. 我们丢弃文件的其余部分。即我们将其调整为最终起始字节。那么,剩下的就是我们的新字符串。

  5. 文件越大,操作时间越长。不幸的是,你无能为力。如果文件很大,这是你最好的选择。该过程与从内存数组的开始/中间删除项目时的过程相同,除了必须缓冲(以块为单位)不要过多填充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()