如何将一个文件夹中的多个文件打包为一个二进制文件,并获取每个文件的偏移量? [关闭]

问题描述 投票:0回答:1
我的文件夹中有很多文件,我想将所有文件打包成一个二进制文件,并获取其中每个文件的偏移量。有人可以帮我吗?现在我的代码(非常糟糕的代码,顺便说一句,我是Python的新手):

import os import os.path for dirpath, dirnames, filenames in os.walk("."): for filename in [f for f in filenames if f.endswith(".RTON")]: print(os.listdir(os.path.join(filename))) a = os.path.join(filename)

例如:在我的文件夹中,我有100个文件,想要将它们打包在一起并获取每个文件的偏移量。

packed_file = file1 + file2 + file3...+ file100

生成的二进制文件应该是1个文件,其中包含打包到其中的所有其他文件的数据。打个比方是tarball
python python-3.x file pack
1个回答
0
投票
这实际上是一个通用编程问题,并非特定于python,因此我将以通用方式回答。这几乎适用于所有主要语言。

简单文件表

一种典型的方法是使创建的文件的开头包含其中所有文件的映射。

由于您可以选择以任何方式写入(然后从中读取)二进制文件,因此可以根据需要设置此映射。您只需要决定如何使数据代表文件结构即可。

一种相对简单的方法可能是使用文件中的前几个字节作为计数器(我称其为N),它告诉您打包文件中总共包含多少个源文件,然后使用下一个N * 4或N * 8字节,表示打包文件中可以找到每个源文件的位置。然后在4 + N * 4(或8 + N * 8,或其他)字节之后,接下来可以一次放置一个文件。如果要包含文件名,可以将名称放在文件数据之前的位置。

一个用例:

我有5个源文件要存储到您的大包装文件中:

    stuff / a / hi.txt(包含“ Hello world!”))
  • stuff / a / bye.txt(包含“再见的世界!”)
  • stuff / b / abc.txt(包含“ abcdefg”)
  • stuff / b / def.txt(包含“ gfedcba”)]
  • stuff / b / ghi.txt(包含“ mnopqrstuv”)
  • 我可以这样保存数据:(请注意:下面每个项目符号中的第一个数字是文件中的位置,数据在文件中的字节数,我假设是4字节的整数,因此这些数字将占用4个字节,也假定是1个字母= 1个字节的文本字符串格式,可能不是这种情况)

      0:5(#个文件:后5 * 4个字节用于文件位置)
  • 4:24(hi.txt位置)
  • 8:50(bye.txt位置)
  • 12:79(abc.txt位置)
  • 16:101(def.txt位置)
  • 20:123(ghi.txt位置)
  • 24:6(以下文件名使用多少字节)
  • 28:“ hi.txt”(存储在二进制文件中的文件名数据)
  • 34:12(文件长度)
  • 38:“世界你好!” (文件的数据打包到打包文件中)
  • 50:7(文件#2的文件名长度)
  • 54:“ bye.txt”(#2的文件名)
  • 61:14(文件长度)
  • 65:“再见的世界!”
  • 79:7(#3文件名长度)
  • 83:“ abc.txt”
  • 90:7(数据长度)
  • 94:“ abcdefg”
  • 101:7(#4文件名长度)
  • 105:“ def.txt”
  • 112:7(数据长度)
  • 116:“ gfedcba”
  • 123:7(#5文件名长度)
  • 127:“ ghi.txt”
  • 134:10(数据长度)
  • 138:“ mnopqrstuv”
  • 148:没有更多数据,147是最后一个文件位置
  • 要获得打包文件中包含哪些文件的列表,您只需执行(伪代码):

    number-files = read the first 4-byte integer N = 1..number-files location[N] = read a 4-byte integer from location N name-length[N] = read a 4-byte integer from location location[N] file-names[N] = read text string: name-length[N] bytes at location[N]+4

    然后,要读取文件的数据(N是数字):

    N = pick-a-file-any-file(file-names) file-location = read integer at location N file-data-location = file-location + 4 + (read integer at location file-location) data-length = read integer at file-data-location data = read data-length bytes from location (file-data-location + 4)

    并且所选文件的文件数据将在“数据”中。

    改进

    注意:这是

    不是处理文件表的最有效方法。这只是我认为可能最容易理解和遵循的逻辑。

    有许多更有效的方法来处理文件结构。如何优化表取决于要优化的内容。如果您需要最大速度浏览庞大的文件表,则表中可能包含以下内容:

      文件数(N)
  • N对(文件名位置,文件数据位置)
  • N个文件名
  • N个文件数据
  • 这可以改善局部性(一种相似的数据在内存或磁盘中的紧密程度的属性,可以缩短访问时间,并且还使得从拥有文件X到查找X的名称变得更加容易或数据。

    [某些系统使用的另一种改进是仅从以4096整除的位置开始文件的数据:因此,文件1的数据可以位于4096位置,文件2的数据可以位于8192,依此类推。)由于从磁盘读取数据的方式。

    当然,如果您有很多小文件,那么您不希望它们全部基于4096对齐,否则您的文件可能比需要的大数千倍。因此,另一个改进是在文件中具有不同的部分,其中的一些部分是4096对齐的,而有些则没有。在上面的用例中,有5个小文件(最大10个字节),您希望它们全部位于同一磁盘扇区中。但是,如果您有任何大文件,将它们对齐到4096可分割的位置将很有意义。

    [您如何处理1个文件的末尾与下一个文件的开始之间的其余空间(即:如果将“ abcdefg”保存为4096,并将gfedcba保存为8192,那么您如何处理来自4104至8191)?那是死空间,您只需将其全部设置为一堆零即可。是的,它浪费了,这就是为什么您不想只对大文件执行此操作的原因。

    更新文件

    假设您已经编写了文件,然后在计算机上将abc.txt更改为包含“ abcdefghijklmnop”,并且您想更新已创建的打包文件。怎么办? “ abcdefghijklmnop”不适合您在打包文件中为其保留的空间,因此您不能仅插入它。

    如果要在适当位置编辑文件,则需要以一种易于容纳此类更改的方式保存数据。例如,如果我们将文件数据对齐到前面提到的4096个可分割的位置,那么我们将剩下大量的死区,还有足够的空间来容纳此更改。

    或者,您可以重新排列一些数据以容纳它。您可以将下一个文件移到文件末尾并使用其一些空间。这变得越来越复杂,不是吗?

    一种简单的更新文件的方法是每次更新时都重新创建它;甚至不必费心尝试更改文件的一小部分,每次都覆盖整个内容。对于巨大的文件结构,这可能会花费很多时间,但是对于不需要很好缩放的小型文件结构,它可以工作。

    碎片整理

    对于上一节,如果您选择艰难的方式并仅在文件结构已更改的地方更新文件结构,而不是重写整个文件,那么对您有好处,但情况还会变得更糟...

    如果您在文件中移动足够多的内容,最终文件数据可能会无处不在,如果您将内容移动足够多,则可能会有很多死区。最终可能会产生大量开销。

    如果您要继续沿着这条路径进行优化,下一步将是改进用于移动内容的算法,或者实施碎片整理算法来修复文件的低效率。

    如您所见,沿着这条路径进行优化越来越令人头疼。因此,如果不需要,通常不会完成。

    摘要

    您需要决定您的需求,这取决于您为什么这样做。如果您只有一些小项目,例如个人项目或课堂作业,那么像第一部分中的简单方法这样的东西就足够了,如果您掌握得足够好,可以进行一些小的优化,然后可以重写打包的内容。 -文件,每次更新时。

  • © www.soinside.com 2019 - 2024. All rights reserved.