如何检测文件中是否存在数据 C 文件处理

How to detect if there exists a data in a file C File Handling

我对 C 中的文件处理很陌生。我想问一下是否有任何方法可以检测文件中是否存在现有数据。因为如果有none,我会用"wb",但如果已经有数据,我就用append "ab".

我尝试在写入数据时使用"wb"而不是"ab",但是我写入的第一个数据无法读取。

这是一个例子:

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

struct clientInfo{
    char Name[30];
};

void inputAccounts();
void viewAllRecords();

int main()
{
    showOptions();
}

void inputData()
{
    FILE *fp;

    fp = fopen("hello", "ab");

    struct clientInfo PERSONAL;

    if(fp == NULL)
    {
        printf("Error!!!");
        getch();
    }
    else
    {
        fflush(stdin);
        printf("Enter Name: ");
        gets(PERSONAL.Name);

        fwrite((char *)&PERSONAL, sizeof(struct clientInfo), 1, fp);

        printf("File Created!!!");
        getch();
        fclose(fp);
    }
}

void showOptions()
{
    char choice;
    system("cls");
    printf("\n[1] Add Accounts");
    printf("\n[2] View Records");
    choice = getch();
    if (choice == '1')
    {
        inputData();
    }
    else if (choice == '2')
    {
        viewAllRecords();
    }
    showOptions();
}

void viewAllRecords()
{
    FILE *fp;
    fp = fopen("hello", "rb");

    struct clientInfo PERSONAL;

    fread((char *)&PERSONAL, sizeof(struct clientInfo), 1, fp);

    system("cls");
    if(fp == NULL){
        printf("Error!!!");
        getch();
    }
    else
    {
        while((fread((char *)&PERSONAL, sizeof(struct clientInfo), 1, fp))==1)
        {
            printf("Name: %s\n", PERSONAL.Name);
        }
    }
    getchar();
}

您可以使用 fseek() 来实现您的目的。 fseek() 用于将与给定文件关联的文件指针移动到特定位置。

FILE *fp;
fp = fopen("test.txt", "r");
// Moving pointer to end
fseek(fp, 0, SEEK_END);
if(ftell(fp)>0){
    printf("data exists on the file.\n");
}else{
    printf("no data.\n");
}

有关详细信息,您可以阅读 this 文章。

在所有情况下都使用 ab

如果文件已经存在,则打开文件并从文件末尾开始写入。

如果不存在,则创建并从文件末尾开始写入,与文件开头相同。

来自http://man7.org/linux/man-pages/man3/fopen.3.html

   a      Open for appending (writing at end of file).  The file is
          created if it does not exist.  The stream is positioned at the
          end of the file.

编辑

由于 OP 发布了更多代码,因此可以看出第一个条目永远不会被打印:

struct clientInfo PERSONAL;

fread((char *)&PERSONAL, sizeof(struct clientInfo), 1, fp);
^^^^^^^
Read but there is no print

system("cls");
if(fp == NULL){
    printf("Error!!!");
    getch();
}
else
{
    while((fread((char *)&PERSONAL, sizeof(struct clientInfo), 1, fp))==1)
    {
        printf("Name: %s\n", PERSONAL.Name);
    }
}

解决方案很简单 - 只需删除 fread 以便 fread 仅在 while 循环中完成。

其他提示:

对于 gets 参见 Why is the gets function so dangerous that it should not be used?

对于 fflush(stdin);,请参阅 Using fflush(stdin)

标准库还提供了statfstat函数,可以让你填一个struct stat直接判断文件大小。 stat 采用文件路径和指向 stuct stat 的指针(使用自动存储声明是可以的),而 fstat 采用整数文件描述符作为其参数。

使用stat判断文件大小是否大于零,调用stat然后检查.st_size结构成员很简单。

通过适当的验证,您可以:

#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>

#define MAXC 1024

int main (void) {

    char fn[MAXC];      /* filename */
    struct stat sbuf;   /* stat buffer */
    FILE *fp;

    /* prompt, read filename, trim line-end */
    fputs ("enter filename: ", stdout);
    if (!fgets (fn, MAXC, stdin)) {
        fputs ("(user canceled input)\n", stderr);
        return 1;
    }
    fn[strcspn (fn, "\r\n")] = 0;

    /* call stat, fill stat buffer, validate success */
    if (stat (fn, &sbuf) == -1) {
        perror ("error-stat");
        return 1;
    }

    /* test sbuf.st_size to check if file size > 0 */
    if (sbuf.st_size > 0) {
        puts ("opened ab");
        fp = fopen (fn, "ab");
    }
    else {
        puts ("opened wb");
        fp = fopen (fn, "wb");
    }
    /* rest of code... */
}

无论哪种方式,使用 seekstat,您都可以确定您需要什么。