【问题标题】:What the best approach to iterate and "store" files over a directory in C (Linux)?在 C (Linux) 中的目录上迭代和“存储”文件的最佳方法是什么?
【发布时间】:2010-04-23 08:14:23
【问题描述】:

我编写了一个函数来检查文件是否重复。这个函数签名是:

int check_dup_memmap(char *f1_name, char *f2_name)

返回:

  • (-1) - 如果出现问题;
  • (0) - 如果两个文件相似;
  • (+1) - 如果两个文件不同;

下一步是编写一个函数,遍历某个目录中的所有文件,应用前面的函数,并给出每个现有重复项的报告。

最初我想写一个函数来生成一个包含特定目录中所有文件名的文件,然后再次读取该文件并获取并比较每两个文件。这是该函数的版本,它获取某个目录中的所有文件名。

void *build_dir_tree(char *dirname, FILE *f)
{
    DIR *cdir = NULL;
    struct dirent *ent = NULL;
    struct stat buf;
    if(f == NULL){
        fprintf(stderr, "NULL file submitted. [build_dir_tree].\n");
        exit(-1);   
    }
    if(dirname == NULL){
        fprintf(stderr, "NULL dirname submitted. [build_dir_tree].\n");
        exit(-1);
    }
    if((cdir = opendir(dirname)) == NULL){
        char emsg[MFILE_LEN];
        sprintf(emsg, "Cannot open dir: %s [build_dir_tree]\t",dirname);
        perror(emsg);
    }
    chdir(dirname);
    while ((ent = readdir(cdir)) != NULL) {
        lstat(ent->d_name, &buf);
        if (S_ISDIR(buf.st_mode)) {
            if (strcmp(".", ent->d_name) == 0 ||
                    strcmp("..", ent->d_name) == 0) {
                continue;
            }
            build_dir_tree(ent->d_name, f);
        }
        else{
            fprintf(f, "/%s/%s\n",util_get_cwd(),ent->d_name);
        }
    }
    chdir("..");
    closedir(cdir);
}

我仍然认为这种方法有点低效,因为我必须一次又一次地解析文件。

您认为我应该遵循哪些其他方法:

  • 编写数据结构并保存文件而不是将它们写入文件?我觉得对于一个文件很多的目录,内存会变得很碎片化。
  • 将所有文件名保存在自动扩展数组中,以便我可以通过索引轻松访问每个文件,因为它们将位于连续的内存位置。
  • 使用 mmap() 将此文件映射到内存中?但随着文件变大,mmap 可能会失败。

对此有任何意见。我想选择最有效的路径,并尽可能少地访问资源。这是程序的要求……

编辑: 有没有办法在不遍历它的情况下获取某个目录中的文件数?

【问题讨论】:

  • 为什么要在操作之前读取所有目录条目?我会把你的目录读取函数变成一个 for_each 函数,你传递了一个目录名、一个函数指针和一个 void * 参数。该函数将接受一个 char * 参数,它是读取的目录名称(或者您可以继续打开它并传递 FILE 或 fd),并且可能还有一个 void * ,这只是您需要提供给它的任何其他内容。然后这个函数会调用你的比较函数。

标签: c linux posix


【解决方案1】:

您可能想要使用哈希或校验和;创建每个文件内容的散列,并将每个散列与具有该散列的文件名列表相关联。然后,当您构造哈希时,您将看到哪些其他文件也共享相同的哈希。只有当你遇到冲突时,你才真正需要比较完整的文件。如果你选择了一个好的散列函数,那么冲突应该是比较少见的,所以比较少见。

请注意,哈希大小和冲突次数之间存在权衡;如果您使用较小的散列,冲突可能会更频繁,但每个文件将使用更少的空间,如果您使用较大的散列,那么您将不得不做更少的完整文件比较,但需要坚持和比较更大的哈希值。此外,一些散列函数导致的冲突比其他散列更少,但一些更好的散列函数可能比较差的散列函数更耗时和计算密集。

一种有效的文件和目录遍历方法是使用ftwnftw

【讨论】:

  • 在我看来散列是没有必要的?问题仍然是如何存储文件名。在什么类型的数据结构中?
  • @Andrei,您将使用哈希表,将文件的哈希映射到字符串的链接列表,其中每个字符串都包含文件的路径。
  • 如果没有任何类型的哈希,您将如何检查重复项?对于每个文件,将整个文件内容与目录中所有其他文件的整个文件内容进行比较?当然,您可以先检查文件大小是否与第一种情况相同-(尽管我这里有一个目录,其中也有 300k+ 个相同大小的文件)与对所有文件进行一次散列并进行比较相比,这将非常慢如果发生碰撞,则内容一次。
  • +1,在 f/nftw() 回调中实现一个简单的哈希是非常容易的。只是不要相信将 ftw/nftw 描述为使用广度优先算法的旧文档。我遇到过这样的手册页。
猜你喜欢
  • 1970-01-01
  • 2013-02-15
  • 2017-11-21
  • 2011-01-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-07-06
  • 1970-01-01
相关资源
最近更新 更多