fgets() 不读取整个文件
fgets() does not read the whole file
我正在编写一个程序,主要用于搜索目录及其所有子目录以查找重复文件。我根据您的建议改进了问题和代码(需要 return 默认值的函数已被修复)所以这里是...
这里是比较函数的代码:
int compare()
{
int a, b;
unsigned char byte1, byte2;
while(1)
{
a = fread(&byte1, 1, 1, file1);
b = fread(&byte2, 1, 1, file2);
if(a == 0 && b == 0) break;
if(a != b) return 1;
if(byte2 != byte1) return 1;
}
return 0;
}
void startCompare()
{
char path1[1000], path2[1000];
FILE *reference = fopen("list.comp", "r");
FILE *other = fopen("list2.comp", "r");
int i, flag, j;
i = 0;
while(fgets(path1, 1000, reference))
{
flag = 0;
strtok(path1, "\n");
openFile1(path1);
for(j = 0; j <= i; ++j)
{
fgets(path2, 1000, other);
}
while(fgets(path2, 1000, other))
{
strtok(path2, "\n");
openFile2(path2);
if(!compare())
{
printf("Checking: %s vs. %s --> DUPLICATE\n", path1, path2);
flag = 1;
break;
}
else
{
printf("Checking: %s vs. %s --> DIFFERENT\n", path1, path2);
}
}
if(flag == 1)
{
printf("Will be deleted.\n");
}
}
}
(先调用startCompare()函数)
现在,目录本身有这些文件:
- bloblo
- bloblo/frofo
- bloblo/frofo/新建文件夹
- bloblo/frofo/新建文件夹(2)
- bloblo/frofo/新建文件夹 (2)/新建文件夹 (3)
- bloblo/frofo/新建文件夹 (2)/新建文件夹 (3)/新建文本 Document.txt
- bloblo/frofo/新建文件夹 (2)/新建文件夹 (3)/Untitled4
- 0.comp
- 1.comp
- 2.comp
- 3.comp
- 4.comp
- 5.comp
- 11.comp
- 100.comp
- duplicate_delete.dev
- duplicate_delete.exe
- duplicate_delete.layout
- list.comp
- 列表2.comp
- main.c
- main.o
- Makefile.win
- Untitled5.c
- Untitled5.exe
输出为:
Checking: 0.comp vs. 1.comp --> DIFFERENT
Checking: 0.comp vs. 100.comp --> DIFFERENT
Checking: 0.comp vs. 11.comp --> DIFFERENT
Checking: 0.comp vs. 2.comp --> DIFFERENT
Checking: 0.comp vs. 3.comp --> DIFFERENT
Checking: 0.comp vs. 4.comp --> DIFFERENT
Checking: 0.comp vs. 5.comp --> DIFFERENT
Checking: 0.comp vs. duplicate_delete.dev --> DIFFERENT
Checking: 0.comp vs. duplicate_delete.exe --> DIFFERENT
Checking: 0.comp vs. duplicate_delete.layout --> DIFFERENT
Checking: 0.comp vs. list.comp --> DIFFERENT
Checking: 0.comp vs. list2.comp --> DIFFERENT
Checking: 0.comp vs. main.c --> DIFFERENT
Checking: 0.comp vs. main.o --> DIFFERENT
Checking: 0.comp vs. Makefile.win --> DIFFERENT
Checking: 0.comp vs. Untitled5.c --> DIFFERENT
Checking: 0.comp vs. Untitled5.exe --> DIFFERENT
使用 return 代码 0。
虽然它应该打印的是每个文件相互检查并发现文件 100.comp 和 11.comp 是彼此的副本,而其他文件是唯一的。所以基本上,为什么它停在那里?为什么不继续查?有什么办法可以解决这个问题吗?
我不知道这是否会回答您的 TLDR 问题和代码,但这对于评论来说太多了。
你的函数 compare()
永远不会 returns 0
,如果你已经启用并注意到编译器警告,你就会知道这一点。该函数还使用了可怕的 feof()
。参见 why feof()
is wrong
我建议更换这个
int compare()
{
while(!feof(file1))
{
fread(&byte1, sizeof(unsigned char), 1, file1);
fread(&byte2, sizeof(unsigned char), 1, file2);
if(byte2 != byte1) return 1;
}
if(feof(file1) && (!feof(file2))) return 1;
if(feof(file2) && (!feof(file1))) return 1;
}
这样,因为检查fread()
读取的数据量是测试文件结束的方法。
int compare()
// return 0 if files are the same
// *** always include a comment to tell you what the function does / returns ***
{
size_t read1, read2;
while(1) {
read1 = fread(&byte1, 1, 1, file1);
read2 = fread(&byte2, 1, 1, file2);
if (read1==0 && read2==0)
break; // success: both files ended
if (read1 != read2)
return 1; // bad: one of them read, other didn't
if (byte2 != byte1)
return 1; // bad: files read different data
}
return 0;
}
注意 sizeof(unsigned char)
是完全没有必要的,它是 1.
我也会将 byte1
和 byte2
作为局部变量。
回答您实际提出的问题(为什么不比较所有文件对):
您的程序首先读取 list.comp
的第一行。然后,它从 list2.comp
中读取每一行并比较文件。
然后,它从 list.comp
读取下一行,并再次尝试将其与 list2.comp
的所有文件进行比较。但它已经在 list2.comp
的末尾,所以它不再从 list2.comp
.
读取任何文件名
您可以使用 rewind(other);
来 "rewind" 回到 list2.comp
的开头,这样您就可以再次读取文件名。
抱歉,如果您要搜索重复文件,则说明您使用的方法效率低下。最好对它们进行 运行 md5sum(1) 并对生成的列表进行排序。然后,您将比较一行与下一行是否相等的 md5 值。如果你不相信 md5sum(1) (有人说不同的文件可以给出相同的校验和),你可以只比较文件内容(但只比较已经匹配的 md5 校验和).到目前为止,这比您的方法有效得多。可以这样解决:
find <dir> -type f -name "glob_pattern" -print0 | xargs -0 md5sum | sort >files.md5sum
然后,编辑文件 files.md5sum
并搜索 /^\([0-9a-f]*\) .*\n/
模式以获取重复的 md5。您甚至会得到同一文件的多次重复。
备注
注意空文件具有相同的 MD5 校验和,并且所有文件都比较相等。您也会在列表中看到它。
我正在编写一个程序,主要用于搜索目录及其所有子目录以查找重复文件。我根据您的建议改进了问题和代码(需要 return 默认值的函数已被修复)所以这里是...
这里是比较函数的代码:
int compare()
{
int a, b;
unsigned char byte1, byte2;
while(1)
{
a = fread(&byte1, 1, 1, file1);
b = fread(&byte2, 1, 1, file2);
if(a == 0 && b == 0) break;
if(a != b) return 1;
if(byte2 != byte1) return 1;
}
return 0;
}
void startCompare()
{
char path1[1000], path2[1000];
FILE *reference = fopen("list.comp", "r");
FILE *other = fopen("list2.comp", "r");
int i, flag, j;
i = 0;
while(fgets(path1, 1000, reference))
{
flag = 0;
strtok(path1, "\n");
openFile1(path1);
for(j = 0; j <= i; ++j)
{
fgets(path2, 1000, other);
}
while(fgets(path2, 1000, other))
{
strtok(path2, "\n");
openFile2(path2);
if(!compare())
{
printf("Checking: %s vs. %s --> DUPLICATE\n", path1, path2);
flag = 1;
break;
}
else
{
printf("Checking: %s vs. %s --> DIFFERENT\n", path1, path2);
}
}
if(flag == 1)
{
printf("Will be deleted.\n");
}
}
}
(先调用startCompare()函数)
现在,目录本身有这些文件:
- bloblo
- bloblo/frofo
- bloblo/frofo/新建文件夹
- bloblo/frofo/新建文件夹(2)
- bloblo/frofo/新建文件夹 (2)/新建文件夹 (3)
- bloblo/frofo/新建文件夹 (2)/新建文件夹 (3)/新建文本 Document.txt
- bloblo/frofo/新建文件夹 (2)/新建文件夹 (3)/Untitled4
- 0.comp
- 1.comp
- 2.comp
- 3.comp
- 4.comp
- 5.comp
- 11.comp
- 100.comp
- duplicate_delete.dev
- duplicate_delete.exe
- duplicate_delete.layout
- list.comp
- 列表2.comp
- main.c
- main.o
- Makefile.win
- Untitled5.c
- Untitled5.exe
输出为:
Checking: 0.comp vs. 1.comp --> DIFFERENT
Checking: 0.comp vs. 100.comp --> DIFFERENT
Checking: 0.comp vs. 11.comp --> DIFFERENT
Checking: 0.comp vs. 2.comp --> DIFFERENT
Checking: 0.comp vs. 3.comp --> DIFFERENT
Checking: 0.comp vs. 4.comp --> DIFFERENT
Checking: 0.comp vs. 5.comp --> DIFFERENT
Checking: 0.comp vs. duplicate_delete.dev --> DIFFERENT
Checking: 0.comp vs. duplicate_delete.exe --> DIFFERENT
Checking: 0.comp vs. duplicate_delete.layout --> DIFFERENT
Checking: 0.comp vs. list.comp --> DIFFERENT
Checking: 0.comp vs. list2.comp --> DIFFERENT
Checking: 0.comp vs. main.c --> DIFFERENT
Checking: 0.comp vs. main.o --> DIFFERENT
Checking: 0.comp vs. Makefile.win --> DIFFERENT
Checking: 0.comp vs. Untitled5.c --> DIFFERENT
Checking: 0.comp vs. Untitled5.exe --> DIFFERENT
使用 return 代码 0。
虽然它应该打印的是每个文件相互检查并发现文件 100.comp 和 11.comp 是彼此的副本,而其他文件是唯一的。所以基本上,为什么它停在那里?为什么不继续查?有什么办法可以解决这个问题吗?
我不知道这是否会回答您的 TLDR 问题和代码,但这对于评论来说太多了。
你的函数 compare()
永远不会 returns 0
,如果你已经启用并注意到编译器警告,你就会知道这一点。该函数还使用了可怕的 feof()
。参见 why feof()
is wrong
我建议更换这个
int compare()
{
while(!feof(file1))
{
fread(&byte1, sizeof(unsigned char), 1, file1);
fread(&byte2, sizeof(unsigned char), 1, file2);
if(byte2 != byte1) return 1;
}
if(feof(file1) && (!feof(file2))) return 1;
if(feof(file2) && (!feof(file1))) return 1;
}
这样,因为检查fread()
读取的数据量是测试文件结束的方法。
int compare()
// return 0 if files are the same
// *** always include a comment to tell you what the function does / returns ***
{
size_t read1, read2;
while(1) {
read1 = fread(&byte1, 1, 1, file1);
read2 = fread(&byte2, 1, 1, file2);
if (read1==0 && read2==0)
break; // success: both files ended
if (read1 != read2)
return 1; // bad: one of them read, other didn't
if (byte2 != byte1)
return 1; // bad: files read different data
}
return 0;
}
注意 sizeof(unsigned char)
是完全没有必要的,它是 1.
我也会将 byte1
和 byte2
作为局部变量。
回答您实际提出的问题(为什么不比较所有文件对):
您的程序首先读取 list.comp
的第一行。然后,它从 list2.comp
中读取每一行并比较文件。
然后,它从 list.comp
读取下一行,并再次尝试将其与 list2.comp
的所有文件进行比较。但它已经在 list2.comp
的末尾,所以它不再从 list2.comp
.
您可以使用 rewind(other);
来 "rewind" 回到 list2.comp
的开头,这样您就可以再次读取文件名。
抱歉,如果您要搜索重复文件,则说明您使用的方法效率低下。最好对它们进行 运行 md5sum(1) 并对生成的列表进行排序。然后,您将比较一行与下一行是否相等的 md5 值。如果你不相信 md5sum(1) (有人说不同的文件可以给出相同的校验和),你可以只比较文件内容(但只比较已经匹配的 md5 校验和).到目前为止,这比您的方法有效得多。可以这样解决:
find <dir> -type f -name "glob_pattern" -print0 | xargs -0 md5sum | sort >files.md5sum
然后,编辑文件 files.md5sum
并搜索 /^\([0-9a-f]*\) .*\n/
模式以获取重复的 md5。您甚至会得到同一文件的多次重复。
备注
注意空文件具有相同的 MD5 校验和,并且所有文件都比较相等。您也会在列表中看到它。