如何从二进制文件中正确读取?

How do I read properly from a binary file?

我已经将我的代码缩减到最少,我认为这就是我解决问题所需的一切。

我希望用户能够阅读这个结构:

typedef struct {
    char movieTitle[30];
    unsigned int yearPublished;
    char director[50];
    char genre[50];
    float profit;
} movie_t;

来自一个已经有 4 部电影的二进制文件,但也应该能够存储最多 100 部电影结构,如下定义:

//global var.
// ================================================================
#define MAX_STORAGE 100
movie_t movieData[MAX_STORAGE];
movie_t movieRecord;
unsigned int movieCount = 0;

使用我已经在下面编写的代码,我无法以某种方式从文件中读取所有电影,因为我的“计数检查器”每次都告诉我只读取了一部电影。在我的“readFile”函数下方的控制台输出代码中也只显示了一部电影。

// main functions --- read from file
// ================================================================
int
readFile(const char* fileName)
{
    //open file
    FILE* read = fopen(fileName, "rb");
    if (!read)
    {
        printf("ERROR: Could not open the file!\n");
        return -1;
    }
    else
    {
        printf("%s were opened successfully.\n\n", fileName);
    }

    //read from file
    int count = 0;
    while (!feof(read))
    {
        size_t count = fread(&movieRecord, sizeof(movieRecord), 1, read);
        if (count == 0)
        {
            printf("ERROR: Read process was unsuccessful or incomplete!\n");
        }
        if (count == 1)
        {
            printf("Successfully read %i movie.\n", count);
        }
        else
        {
            printf("Successfully read %i movies.\n", count);
        }
        return count;
    }
    fclose(read);

    return 0;
}

这是应该显示文件中所有电影的控制台输出。此外,它们应该显示 1 - 100 之间的数字 (Num.)。

// main functions --- console Output
// ================================================================
void
consoleOutput(movie_t movieData2, unsigned index)
{
    printf("MOVIE DATA         Num. %u\n\n", index);

    printf("Movie title     : %s\n", movieData2.movieTitle);
    printf("Publishing year : %u\n", movieData2.yearPublished);
    printf("Director        : %s\n", movieData2.director);
    printf("Genre           : %s\n", movieData2.genre);
    printf("Profit          : %.2f\n", movieData2.profit);
}

这是我的主要功能的样子,如果你想看的话:

// MAIN
// ================================================================
int main(void)
{
    // defaultname for file
    char fileName[50] = "movies.dat";

    // variable for loop
    int stopLoop = 0;

    // loop
    do {
        // Output menu
        printf("\nMENU:\n");
        printf("(a)   Show all movies\n");
        printf("(o)   Read moviefile\n");
        printf("(q)   Exit programm\n");
        printf("\nYour choice: ");

        // User input
        char ch = _getch();
        printf("%c\n\n", ch);

        // Switch case for user input
        switch (ch)
        {
        case 'q': // Exit programm
            stopLoop = 1;
            break;
        case 'a': // Show all movies
            consoleOutput(movieRecord, movieCount = readFile(fileName));
            break;
        case 'o': // Read moviefile
            readFile(fileName);
            break;
        default:
            printf("==> Invalid input!\n");
        }

    } while (!stopLoop);

    return 0;
}

旁注:因为用户能够输入新电影,所以他们应该能够将该数据保存到他们读取的同一个文件中。但这是我想先测试自己的东西,然后再四处寻求帮助。

您只读了一个条目就从循环体返回。如果您真的想读取文件中的所有条目,则需要将读取循环更改为读取数组,实际上,由于 fread 的工作原理,您可以将其全部删除:

// main functions --- read from file
// ================================================================
int
readFile(const char* fileName)
{
    //open file
    FILE* read = fopen(fileName, "rb");
    if (!read)
    {
        printf("ERROR: Could not open the file!\n");
        return 0; // note that since you'll probably assign the output to movieCount, it might be better to return 0 on failure
    }
    else
    {
        printf("%s were opened successfully.\n\n", fileName);
    }

    // Here's where the problem, you only ever read out one movie entry into movieRecord and returned
    // You can use fread to read out the entire file into the array instead
    // It would also be better not to use a global variable for this, instead taking in a pointer to an movie_t array to readFile instead but I left it using the global as per the original program
    size_t count = fread(movieData, sizeof(movie_t), MAX_STORAGE, read);
    if (ferror(read))
    {
        printf("ERROR: Read process was unsuccessful or incomplete!\n");
        fclose(read);
        return 0;
    }
    if (count == 1)
    {
        printf("Successfully read %i movie.\n", count);
    }
    else
    {
        printf("Successfully read %i movies.\n", count);
    }
    fclose(read);

    return count;
}

从这里开始,您将 movieData 填充文件中的数据,并应相应地调整程序的其余部分。