Home > Back-end >  How to initialize a file only once
How to initialize a file only once

Time:12-27

  • I have this function for initializing admin account,

  • the adminAcc.txt should be initialized only once, regardless of how many times the program has been executed. .

  • The code does not work tho, it still initializes the file everytime i run the program,

anyone can help? ty...

static int file_initialized = 0; //global variable

void initAdmin(){
  struct form adminAcc;

  FILE *fptr;
  
  if((fptr = fopen("adminAcc.txt", "a")) == NULL){
    printf("\nError Opening Admin File!");
    getch();
    system("cls");  
    main();
  }

  if(file_initialized != 1){
    strcpy(adminAcc.username, "[email protected]");
    strcpy(adminAcc.password, "admin");
    strcpy(adminAcc.roles, "admin");

    fwrite(&adminAcc, sizeof(struct form), 1, fptr);
    file_initialized = 1;
  }else{
    return;
  }

  fclose(fptr);
}

int main(){
  initAdmin();

  return 0;
}

CodePudding user response:

If you want to retain the value of file_initialized across calls (as your code implies) you need to make it static:

  static int file_initialized = 0;

If you only want to initialize it once across multiple program executions, then you need to persist the initialization state. Below I inspect the position of newly opened file and initialize it if empty:

#include <errno.h>
#include <stdio.h>

#define FILENAME "adminAcc.txt"
#define LEN 64

struct form {
    char username[LEN];
    char password[LEN];
    char roles[LEN];
};

int initAdmin(){
    FILE *fptr = fopen(FILENAME, "a");
    if(!fptr) {
        printf("Error Opening Admin File!\n");
        return 1;
    }
    if(!ftell(fptr)) {
        printf("initialize\n");
        fwrite(
            &(struct form) { "[email protected]", "admin", "admin" },
            sizeof(struct form),
            1,
            fptr
        );
    }
    fclose(fptr);
    return 0;
}

int main() {
    initAdmin();
}

and example runs:

$ ./a.out
initialize
$ ./a.out
$

CodePudding user response:

sorry for not updating...

this is how i solved the problem:

  • I included the library below, to use access() function.
#include <unistd.h> 
  • The access() function checks to see if the file or directory specified by path exists and if it can be accessed with the file access permissions given by amode.

  • the function will only create and initialize a file named(filename) if the file does not exists, otherwise skip the initialization

void initAdmin(){
  struct form adminAcc;

  if(access("adminAcc.txt", F_OK) == -1){
    FILE *fptr = fopen("adminAcc.txt", "w");

    strcpy(adminAcc.username, "[email protected]");
    strcpy(adminAcc.password, "admin");
    strcpy(adminAcc.roles, "admin");

    fwrite(&adminAcc, sizeof(struct form), 1, fptr);
    fclose(fptr);
  }
}

CodePudding user response:

The code does not work tho, it still initializes the file everytime i run the program

You cannot retain program state in the program across multiple runs. Every run of the program starts with a clean slate. Depending on the system on which it runs, however, you can generally retain state in the system. In this case, the natural state is whether the adminAcc.txt file exists, and possibly whether it has valid contents.

Although it is possible to check that before trying to open the file, a better paradigm is usually simply to attempt an operation (such as opening the file) and seeing whether that works. Because you need to do that anyway, and it's always possible for the system to be modified at just the right time such that the wanted operation fails even though an appropriate pre-check predicts that it will succeed.

So, something along these lines would make sense, then:

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

void initAdminIfNecessary(){
  struct form adminAcc;

  FILE *fptr;
  
  if((fptr = fopen("adminAcc.txt", "ab")) == NULL){
    fprintf(stderr, "\nError Opening Admin File!\n");
    abort();
  }

  long fileSize = ftell(fptr);

  if (fileSize == -1) {
    fprintf(stderr, "\nError determining Admin File length!\n");
    abort();
  else if (fileSize == 0) {
    strcpy(adminAcc.username, "[email protected]");
    strcpy(adminAcc.password, "admin");
    strcpy(adminAcc.roles, "admin");

    fwrite(&adminAcc, sizeof(struct form), 1, fptr);
    // TODO: check return value
  } else if (fileSize < sizeof(struct form)) {
    fprintf(stderr, "\nAdmin File has invalid content\n");
    abort();
  }

  fclose(fptr);
}

int main(){
  initAdminIfNecessary();

  return 0;
}

That opens the file as a binary (b) file in append (a) mode, which creates it if it does not already exist, but does not modify it if it does exist. The file is initially positioned at its end (and each write will go to the then-end of the file).

It uses ftell() to determine the length of the file, and acts accordingly.

  • Related