用于POSIX操作系统的C文件浏览器

用于POSIX操作系统的C文件浏览器,c,C,我已经为嵌入式设备创建了一个文件浏览UI。在嵌入式方面,我能够从硬盘上获取目录中的所有文件,并返回诸如名称、大小、修改等统计信息。这是通过使用opendir和closedir以及while循环来完成的,该循环将遍历每个文件,直到没有文件为止 这很酷,直到文件数量达到大数量。我需要实现分页和排序。假设我在一个目录中有10000个文件——我怎么可能在不破坏RAM(大约1mb的RAM…!)的情况下浏览这些文件并根据大小、名称等进行排序呢。也许硬盘操作系统或驱动程序中已经存在一些东西?这里有两个建议,它

我已经为嵌入式设备创建了一个文件浏览UI。在嵌入式方面,我能够从硬盘上获取目录中的所有文件,并返回诸如名称、大小、修改等统计信息。这是通过使用
opendir
closedir
以及
while
循环来完成的,该循环将遍历每个文件,直到没有文件为止


这很酷,直到文件数量达到大数量。我需要实现分页和排序。假设我在一个目录中有10000个文件——我怎么可能在不破坏RAM(大约1mb的RAM…!)的情况下浏览这些文件并根据大小、名称等进行排序呢。也许硬盘操作系统或驱动程序中已经存在一些东西?

这里有两个建议,它们都占用了很小的内存。第一个将不再使用您希望为请求返回的结果数的内存。它是一个恒定时间O(1)内存-它只取决于结果集的大小,但如果用户确实翻阅所有结果,则最终是二次时间(或更糟):

您只需要查找一个小的分页结果(例如r=25个条目)。您可以通过扫描所有文件名并维护将返回的项目的排序列表来生成这些结果,使用长度为r的插入排序,并且对于插入的每个文件,仅保留前r个结果。(实际上,如果文件F低于rth条目,则不会插入文件F)

您将如何生成第二页的结果?您已经知道上一个请求中的第25个文件,因此在扫描过程中忽略之前的所有条目。(如果对重复字段进行排序,则需要更加努力)

好处是所需的最小内存—所需的内存不会比您希望返回的r结果大多少(如果不缓存名称,甚至可能更小)。缺点是生成完整的结果在时间上与您拥有的总文件数成二次关系。实际上,人们不会对结果进行排序,然后逐页浏览所有页面,所以这可能是可以接受的

如果您的内存预算较大(例如少于10000个文件),但您仍然没有足够的空间对所有10000个文件名执行简单的内存排序,那么seekdir/telldir是您的朋友。i、 e.通过流式传输readdir并使用telldir捕获每个条目的位置,创建一个long数组。(您甚至可以将每个telldir之间的增量压缩为2字节短)。作为一个最小的实现,您可以使用clib的sort函数对它们进行排序,并编写自己的回调函数将位置转换为可比较的值。您的回拨将使用seekdir两次读取这两个文件名

上面的方法太过分了-您只需对所有条目进行排序,只需要一页25页,因此,为了好玩,为什么不阅读Hoare的QuickSelect算法,并使用它的一个版本来确定所需范围内的结果呢。您可以递归忽略所需范围之外的所有条目,只对结果的第一个条目和最后一个条目之间的条目进行排序。

您需要的是一个,这是一个使用外部资源完成的排序,通常在磁盘上。Unix
sort
命令执行此操作。通常情况下,这是通过一个

算法基本上就是这样。让我们假设您想为此投入100k内存(投入越多,磁盘操作越少,运行速度越快)

  • 将100k数据读入内存(即调用
    readdir
    a bunch)
  • 把那10万个大块头整理一下
  • 将大量已排序的数据写入磁盘上自己的文件。
    • 也可以在单个文件中使用偏移
  • 转到1,直到所有大块头都被分类
  • 现在,您在磁盘上有10万个大块头,每个都已排序。假设你有9个大块头。为了保持在100k内存限制内,我们将工作划分为大块数+1。9个大块头加1等于10。100k/10等于10k。现在我们在10公里的街区里工作

  • 把每一个大块头的前10公里读入记忆
  • 再分配10k(或更多)作为缓冲区
  • 对大块头做一个测试。
  • 将任何块中最小的块写入缓冲区。重复一遍
  • 当缓冲区填满时,将其追加到磁盘上的文件中
  • 当一个大块头清空时,读下那个大块头的10公里
  • 当所有大块都为空时,读取结果排序文件
  • 您可能会找到一个库来为您执行此操作


    因为对于小文件列表的正常情况来说,这显然是过分的,所以只有当目录中的文件比内存中的文件多时才使用它


    内存内排序和外部排序都以相同的步骤开始:开始调用
    readdir
    并写入固定大小的数组。如果您在空间不足之前用完了文件,只需对所读内容进行内存快速排序即可。如果空间不足,这将是第一个外部排序。

    “假设一个目录中有10000个文件”由于其他原因(例如索引节点的数量),您不希望在一个目录中有这么多文件。因此,改变程序的设计,将文件均匀地分布在几个子目录甚至一棵子目录树上。这是我无法控制的。对于一个需要处理10000个项目的表的设备来说,1MB的内存不多,不管它们来自何处。每个项目有100个字节。文件名通常允许最长为255字节,但平均长度要短得多。如果不能一次将所有项目存储在内存中,则必须进行外部排序(即,将数据以希望显示的格式放入临时文件,然后对临时文件进行排序)。这并不容易。我建议你像这样将任务一分为二:首先,忘记你必须从目录中收集数据,想象一下你将所有数据都放在一个文件中,以最好的格式完成你要做的事情。然后找出如何实现该文件的交互式排序显示。T