如何使用C语言从目录中的所有文件读取数据?

时间:2015-07-27 17:48:24

标签: c file-io io

我正在尝试1)查找目录中的所有文件并显示它们,2)打开所有找到的文件并从中读取数据(字符)3)将读取的数据输出到屏幕或新文件。

这是在C语言中完成的,您将在下面看到我当前的代码。我遇到的问题是:我可以找到目录中的所有文件并将它们打印到屏幕上(上面的第1点),但是当我尝试打开找到的文件并从中读取数据(字符)时(上面的第2点),我得到了一个分段错误。

如果我注释掉下面的行,但是留下fscanf(entry_file, "%s", files);行,则编译好并将文件写入屏幕。我还尝试使用entry_file = fopen(in_file->d_name, "r");(未在下面显示)对fscanf行编制索引,并产生相同的分段错误。

那么,如何从这些找到的文件中读取数据?谢谢!

int i

3 个答案:

答案 0 :(得分:1)

看到您在使用NULLdir之前正确地检查in_file,唯一可能导致此问题的是entry_file为空。使用前检查一下:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <dirent.h>
#include <unistd.h>
#include <errno.h>

int main()
{
    DIR* dir;
    FILE *entry_file;
    struct dirent *in_file;
    char files[1000];
    int i;

    dir = opendir("/Users/tcn/data");

    if(dir==NULL) {
        printf("Error! Unable to read directory");
        exit(1);
    }

    while((in_file=readdir(dir)) != NULL) {
        if (!strcmp (in_file->d_name, "."))
            continue;
        if (!strcmp (in_file->d_name, ".."))
            continue;
        printf("%s\n", in_file->d_name);
        entry_file = fopen(in_file->d_name, "r");
        if (entry_file != NULL) {
            fscanf(entry_file, "%s", files);
            /* whatever you want to do with files */
            fclose(entry_file);
        }
    }

    closedir(dir);
    return 0;
}

另请注意,正如其他多位用户所评论的那样,您应该在循环中关闭entry_file

答案 1 :(得分:0)

您将需要一个使用fread()循环的函数来替换fscanf行,并执行十六进制转储。首先,您不知道文件是文本文件还是二进制文件。另一方面,段错误可能来自于读取不包含newline的二进制文件到char files[1000];即使文件 所有文本文件,也无法预测您的“慷慨的“1000长度足以容纳第一行文字。

答案 2 :(得分:0)

导致崩溃的两个最可能原因是没有检查fopen的返回值 - 然后在尝试使用fscanffcloseentry_file可能会崩溃当它是NULL时 - 可能会溢出files

另一个不会导致崩溃的问题是in_file->d_name不包含完整路径,而只包含文件名。因此,如果您正在测试/Users/tcn/data中的代码,那么它似乎可以正常工作,但它会在其他地方失败。文件名前缀为/Users/tcn/data/或仅在当前目录(.)上运行。

修正:

if ((entry_file = fopen(in_file->d_name, "r"))) {
    (void) printf("%s\n", in_file->d_name);
    if (fgets(files, sizeof files, entry_file)) { // or `while`?
        // do something with `files`, it will be overwritten for next file
    }
    (void) fclose(entry_file);
}

从代码末尾删除其他fclose(entry_file)

另请注意,如果您将此代码与任意目录一起使用,它可能包含在您尝试读取它们时将永久挂起的管道和/或设备节点。