这个问题与Simulating file system access有关。
我需要随机选择文件和目录作为文件操作的参数,如重命名,写入,读取等。我打算做的是使用其路径制作所有文件和目录的列表,并从中随机选择名单。但是,由于在实际文件系统中创建和删除文件和目录,因此还必须更新列表。我发现维护列表并以这种方式更新它是低效的,它也必须是原子的,以便后面的操作不会访问被前一个操作删除的文件。
你能否建议一种不同的方式来选择文件..可能会从文件系统中直接进行...但是我们如何知道文件的路径呢?
由于
我在这里发现了一些有趣的东西Randomly selecting a file from a tree of directories in a completely fair manner Michael J. Barber的答案,但由于我的愚蠢无知而无法完全遵循它
答案 0 :(得分:3)
当文件系统就在那里时,您不想尝试维护文件列表。您应该可以直接从C执行此操作。从根目录中选择一个随机文件。您可以选择随机最大深度,如果您在此处或之前点击常规文件,请使用它。如果是目录,请重复最大深度。如果它是一个特殊文件,可能重新开始。
这应该很快。操作不应该是原子的。如果要执行操作时文件不存在,请重试。不应该太复杂。您可以在找到目标文件时构建路径。这比直接使用fs更简单(我假设你意味着更低的水平)并且应该很容易实现。
答案 1 :(得分:1)
这是我提出的解决方案。它不是最快的,但应该很快(在准备之后),只使用适度的内存,并且“分布相当好”。当然,这是100%未经测试且有些复杂(无论如何都像保持RB树或类似物一样复杂) - 我很难得使用C; - )
对于目标域中的每个目录,使用文件系统的深度优先步行构建目录树,并记录“之前”文件计数(在树中找到的文件)和“之后”文件count(“之前”计数加上目录中的文件数)。它不应该存储文件本身。 Fast way to find the number of files给出了一些示例C代码。它仍然需要迭代目录内容,但不需要自己存储文件。
计算树中的文件总数。 (这应该只是树中最后一个节点的“后”计数。)
选择[0,max files]范围内的随机数。
导航到树中的节点,使得“之前”文件计数< =随机数< “之后”文件计数。这只是走向(RB-)树结构,本身就是O(lg n)或类似的。
在与所选节点关联的目录中选择一个随机文件 - 确保再次对目录进行计数,并将其用作选择中的[0,limit](如果是关闭,则使用后备)因并发问题导致的最终结果。如果文件数已更改,请确保使用此类信息更新树。如果目录已被删除等,也更新/修复树。(这里的额外完整计数不应该听起来那么糟糕,因为readdir
(平均)必须已经通过1/2导航目录中的条目。但是,应该探索重新计算的好处(如果有的话)。)
根据需要重复步骤2-5。
定期重建整个树(步骤#1)以考虑文件系统更改。删除/添加文件会慢慢扭曲随机性 - 步骤#5可以帮助在某些情况下更新树。重建的频率应通过实验确定。也可以通过重建父/祖父节点或每次通过的[随机]子节点来减少错误引入等。使用修改的时间作为检测变化的快速方法也可能值得研究。
快乐的编码。
答案 2 :(得分:1)
您应该知道的是每个目录中有多少文件才能选择您应该遍历的目录。避免遍历符号链接和计算符号链接中的文件。
您可以使用与描述的pst类似的解决方案。
示例您有3个目录,每个目录中有20,40和1000个文件。 你总计[20,60,1060],你随机数0-1060。如果此数字大于或等于60,则转到第3个文件夹。
一旦到达文件夹白名单文件夹,就会停止遍历。
要通过此路径查找随机文件,您可以像以前一样应用相同的技巧。
通过这种方式,您可以选择任何等于概率的文件。