【问题标题】:How to detect if there exists a data in a file C File Handling如何检测文件中是否存在数据C文件处理
【发布时间】:2019-01-31 05:58:25
【问题描述】:

我对 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();
}

【问题讨论】:

  • 你真正的问题是什么。你失败的代码是什么?如果您提供的细节不佳,我们只能提供通用的解决方案。如果您可以读取除第一组数据之外的所有内容,那么这可能是您的代码中的错误,您没有向我们显示。
  • 你写完后验证你的文件内容了吗?你怎么能确定你的问题是写入文件而不是读取?
  • 我添加了我的程序示例。
  • 递归调用showOptions会吃掉你的堆栈。
  • 在检查NULL之前,您还可以使用fp

标签: c file file-handling


【解决方案1】:

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

【讨论】:

  • fseek() 可能适用于我的目的,但它对我的程序效率不高。我需要一些简单实用的东西。
  • @KenkenCodes 您能否提供更多详细信息,为什么您声称这不是“直接有用”?
【解决方案2】:

在所有情况下都使用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 仅在 whileloop 中完成。

其他提示:

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

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

【讨论】:

    【解决方案3】:

    标准库还提供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,您都可以确定您需要什么。

    【讨论】:

      猜你喜欢
      • 2011-10-21
      • 2011-05-19
      • 2013-04-12
      • 2017-09-10
      • 2013-04-27
      • 1970-01-01
      • 2011-03-27
      • 1970-01-01
      相关资源
      最近更新 更多