ktl159
ktl159

Reputation: 51

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

I am very new to File Handling in C. I would like to ask if there is any way that I could detect if there is an existing data on a file. Because if there's none, I will use "wb", but if there is a data already, I will just use append "ab".

I tried using "wb" instead of "ab" when I write data, but the first data I wrote won't read.

Here is an example:

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

Upvotes: 1

Views: 1225

Answers (3)

4386427
4386427

Reputation: 44274

Simply use ab both all cases.

If the file exists already, it will open the file and writing starts from the end of the file.

If the doesn't exists, it will be created and writing starts from the end of the file which is the same as the beginning.

From 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.

EDIT

Since OP has posted more code it can be seen that the first entry will never be printed:

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);
    }
}

the solution is simple - just remove that fread so that fread is only done in the whileloop.

Other tips:

For gets see Why is the gets function so dangerous that it should not be used?

For fflush(stdin); see Using fflush(stdin)

Upvotes: 1

David C. Rankin
David C. Rankin

Reputation: 84551

The standard library also provides the stat and fstat functions that allow you to fill a struct stat to determine the file size directly. stat takes a file-path and a pointer to a stuct stat (declared with automatic storage is fine), while fstat takes an integer file-descriptor as its argument.

Using stat to determine whether the file size is greater than zero, is a simple matter of calling stat and then checking the .st_size struct member.

With appropriate validation, you could do:

#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... */
}

Either way, using seek or stat, you can determine what you need.

Upvotes: 1

SbrTa
SbrTa

Reputation: 158

You can use fseek() to make your purpose done. fseek() is used to move file pointer associated with a given file to a specific position.

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");
}

for more details you can read this article.

Upvotes: 2

Related Questions