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

时间:2019-01-31 05:58:25

标签: c file file-handling

我对使用C语言进行文件处理非常陌生。我想问一下是否可以通过某种方法检测文件中是否存在现有数据。因为如果没有,我将使用"wb",但是如果已经有数据,我将仅使用附加"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();
}

3 个答案:

答案 0 :(得分:2)

您可以使用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文章。

答案 1 :(得分:1)

在所有情况下都只需使用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)

答案 2 :(得分:1)

标准库还提供了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来确定所需的内容。