使用 feof 函数退出文件

Exiting out of file with feof function

提问人:ckwan 提问时间:7/14/2020 更新时间:7/14/2020 访问量:176

问:

我正在尝试使照片提取程序在检测到它位于要提取的文件的末尾时停止。我通过放置一个 if 条件来做到这一点:

if (feof(file))
{
   return 2;
}

在 fread 函数之后:

fread(array, 1, 512, file);

因此,如果 fread 读取到文件末尾,则 feof 将触发并结束程序。这是我的代码:

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>

int main(int argc, char *argv[])
{
    if (argc != 2)
    {
        printf("Invalid entry.\n");
        return 0;
    }

    int counter = 1;
    FILE* images;
    char jpg_name[8];

    // Check if bytes are jpg. signatures.
    for (int n = 0; counter < 51; n = n + 512)
    {
        // Open file for reading.
        FILE *file = fopen(argv[1], "r");
        if (!file)
        {
            return 1;
        }

        unsigned char array[512];
        fseek(file, n, SEEK_SET);
        fread(array, 1, 512, file); // if EOF, won't have 512 to write into!!!
        if (feof(file))
        {
            return 2;
        }
        fclose(file);

        if (array[0] == 0xff && array[1] == 0xd8 && array[2] == 0xff && (array[3] & 0xf0) == 0xe0)
        {
            // Convert integer to string and store into jpg character array. Increment image number.
            sprintf(jpg_name, "%03i.jpg", counter);
            counter++;

            // Open images file to write into, allocate memory to jpg file to write into, write 512 bytes from array into image file.
            images = fopen(jpg_name, "a");
            fwrite(array, 1, 512, images);
            fclose(images);
        }
        else // If 1st 4 bytes aren't jpg signature.
        {
            if (counter > 1)
            {
                images = fopen(jpg_name, "a");
                fwrite(array, 1, 512, images);
                fclose(images);
            }
        }
    }
}

我还尝试过放置条件:

if (fread(array, 1, 512, file) == 512)

进入程序,使其在读取少于 512 字节后停止运行,以停止自动停止程序,但这似乎也不起作用。

任何澄清或建议将不胜感激,谢谢!

c 恢复 feof

评论

1赞 kaylum 7/14/2020
请描述比“不起作用”更好的行为。输入文件应该是什么,它与正在处理的其他文件有什么关系?argv[1]jpg_name
0赞 William Pursell 7/14/2020
这不是 的目的。在读取操作指示数据已被使用后,您可以使用它来确定读取操作是遇到错误还是读取所有数据。feoffeof
0赞 ckwan 7/14/2020
@kaylum 对不起,没有说得更清楚。argv[1] 是我想从中提取图像的文件的名称。jpg_name与我正在提取的每张图像的名称有关;我正在尝试对jpg进行编号。从 1 开始的数字。由于有 50 张照片要提取,我想在提取所有 50 张图像后停止程序。不幸的是,我的程序不确定何时终止,因此我相信最后一张照片被多次覆盖,我不确定如何解决这个问题。
0赞 ckwan 7/14/2020
@WilliamPursell 所以目前我的“fread”函数一次读取 512 个字节,一旦它到达文件末尾,它会读取文件的最后 512 个字节(因此多次重读最后一张照片的一些早期字节),还是读取 x 个可用的字节,数组的其余部分留空,因为没有更多的字节可以读取?
0赞 William Pursell 7/14/2020
它只会读取尽可能多的可用数据,并将返回读取的总数。之后的数组将保持不变。fread

答:

0赞 Barmar 7/14/2020 #1

不要每次都打开和关闭文件。只需读取块中的文件,直到到达 EOF。512

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>

#define SIZE 512

int main(int argc, char *argv[])
{
    if (argc != 2)
    {
        printf("Invalid entry.\n");
        return 0;
    }

    int counter = 1;
    FILE* images;
    char jpg_name[8];

    // Open file for reading.
    FILE *file = fopen(argv[1], "r");
    if (!file)
    {
        return 1;
    }

    unsigned char array[SIZE];

    // Check if bytes are jpg. signatures.
    while (fread(array, 1, SIZE, file) == 1)
    {
        if (array[0] == 0xff && array[1] == 0xd8 && array[2] == 0xff && (array[3] & 0xf0) == 0xe0)
        {
            // Convert integer to string and store into jpg character array. Increment image number.
            sprintf(jpg_name, "%03i.jpg", counter);
            counter++;

            // Open images file to write into, allocate memory to jpg file to write into, write 512 bytes from array into image file.
            images = fopen(jpg_name, "a");
            fwrite(array, 1, 512, images);
            fclose(images);
        }
        else // If 1st 4 bytes aren't jpg signature.
        {
            if (counter > 1)
            {
                images = fopen(jpg_name, "a");
                fwrite(array, 1, 512, images);
                fclose(images);
            }
        }
    }
    fclose(file);
}

评论

0赞 user3629249 7/15/2020
关于:这不是一个正确的比较。它是调用成功时将返回的第三个参数值。即while (fread(array, 1, SIZE, file) == 1)while ( fread( array, 1, SIZE, file ) == SIZE )
0赞 user3629249 7/15/2020
一遍又一遍地打开/关闭文件是一个糟糕的主意。强烈建议仅使用“4 jpg 标头”字节作为(可能)关闭先前输出文件然后打开新文件的原因
0赞 Barmar 7/15/2020
@user3629249我最初将其移出循环,然后注意到文件名取决于 .我不想用确定何时打开和关闭文件所需的所有逻辑使答案复杂化。实际上并没有那么多开销,因此解决这个问题很重要。counter
0赞 user3629249 7/15/2020
实际上,打开/关闭文件是最有可能发生 I/O 错误的时候。因此,代码应尽量减少这些事件的数量
0赞 Barmar 7/15/2020
@user3629249 或者可能相反,因此您可以尽早发现错误。