如何使用C语言从目录中的所有文件中读取数据?
How to read data from all files in a directory using C Language?
我正在尝试 1) 查找目录中的所有文件并显示它们,2) 打开所有找到的文件并从中读取数据(字符) 3) 将读取的数据输出到屏幕或新文件。
这是用 C 语言完成的,您将在下面看到我当前的代码。我 运行 遇到的问题是:我可以找到目录中的所有文件并将它们打印到屏幕上(上面的第 1 点),但是当我尝试打开找到的文件并读取数据时(字符)(上面第 2 点),我得到一个分段错误。
如果我注释掉下面的 fscanf(entry_file, "%s", files);
行,但保留 entry_file = fopen(in_file->d_name, "r");
行,它编译正常并将文件写入屏幕。我还尝试用 int i
索引 fscanf
行(下面未显示)并产生相同的分段错误。
那么,如何从这些找到的文件中读取数据?谢谢!
#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");
fscanf(entry_file, "%s", files);
}
closedir(dir);
fclose(entry_file);
return 0;
}
鉴于您在使用 dir
和 in_file
之前正确地检查了 NULL
,唯一可能导致这种情况的是 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
循环中关闭。
您将需要一个带有循环的函数,使用 fread()
来替换 fscanf
行,并进行十六进制转储。一方面,您不知道这些文件是文本文件还是二进制文件。另一方面,段错误可能来自将不包含 newline
的二进制文件读入 char files[1000];
即使文件 是 所有文本文件,您也无法预测您的 "generous" 1000 长度足以容纳第一行文本。
崩溃的两个最可能的原因是没有检查 fopen
的 return 值——然后 fscanf
或 fclose
可能会在尝试检查时崩溃在 NULL
时使用 entry_file
– 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)
。
另请注意,如果您将此代码用于任意目录,它可能包含管道 and/or 设备节点,当您尝试读取它们时它们将永远挂起。
我正在尝试 1) 查找目录中的所有文件并显示它们,2) 打开所有找到的文件并从中读取数据(字符) 3) 将读取的数据输出到屏幕或新文件。
这是用 C 语言完成的,您将在下面看到我当前的代码。我 运行 遇到的问题是:我可以找到目录中的所有文件并将它们打印到屏幕上(上面的第 1 点),但是当我尝试打开找到的文件并读取数据时(字符)(上面第 2 点),我得到一个分段错误。
如果我注释掉下面的 fscanf(entry_file, "%s", files);
行,但保留 entry_file = fopen(in_file->d_name, "r");
行,它编译正常并将文件写入屏幕。我还尝试用 int i
索引 fscanf
行(下面未显示)并产生相同的分段错误。
那么,如何从这些找到的文件中读取数据?谢谢!
#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");
fscanf(entry_file, "%s", files);
}
closedir(dir);
fclose(entry_file);
return 0;
}
鉴于您在使用 dir
和 in_file
之前正确地检查了 NULL
,唯一可能导致这种情况的是 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
循环中关闭。
您将需要一个带有循环的函数,使用 fread()
来替换 fscanf
行,并进行十六进制转储。一方面,您不知道这些文件是文本文件还是二进制文件。另一方面,段错误可能来自将不包含 newline
的二进制文件读入 char files[1000];
即使文件 是 所有文本文件,您也无法预测您的 "generous" 1000 长度足以容纳第一行文本。
崩溃的两个最可能的原因是没有检查 fopen
的 return 值——然后 fscanf
或 fclose
可能会在尝试检查时崩溃在 NULL
时使用 entry_file
– 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)
。
另请注意,如果您将此代码用于任意目录,它可能包含管道 and/or 设备节点,当您尝试读取它们时它们将永远挂起。