Frage

I am testing my program to update a number (num_commit) always at the end of the file. This number is used to track how many times the files has been written. I am using lseek/SEEK_END, but I am still trying to figure out how this works. I wrote the following code to test the possibility, but the num_commit seems overwritten. I am looking for help with the correct way of doing this:

#define MAX_PATHNAME_LEN 256

int main()
{
    int commit_times = 10;

    char pathFile[MAX_PATHNAME_LEN];
    sprintf(pathFile, "my_log2.bin");
    int filedescriptor = open(pathFile, O_RDWR | O_CREAT, 0777);

    int num_segs = 10;
    int mods = 200;
    const char *segname = "testfil";
    char real_segname[128];
    strcpy(real_segname, segname); /* in my real program segname is passed into the function */

    lseek(filedescriptor, 0, SEEK_END);  /* write commit_times always at the end of the file */
    write(filedescriptor, &commit_times, sizeof(int));

    lseek(filedescriptor, 0, SEEK_SET);  /* start writing at the beginning */
    write(filedescriptor, &num_segs, sizeof(int));
    int name_length = strlen(real_segname);

    write(filedescriptor, &name_length, sizeof(int));
    write(filedescriptor, real_segname, name_length);
    write(filedescriptor, &mods, sizeof(int));

    commit_times++;                                    /* increment commit_times */
    lseek(filedescriptor, -sizeof(int), SEEK_END);     /* then update the commit_times at the end of the file (overwrite the existing number) */
    write(filedescriptor, &commit_times, sizeof(int));

    close(filedescriptor);

    /* now read back the file */
    int readfd = open(pathFile, O_RDONLY);
    read(readfd, &num_segs, sizeof(int));
    read(readfd, &name_length, sizeof(int));
    read(readfd, real_segname, name_length);
    read(readfd, &mods, sizeof(int));

    int num_commit;
    read(readfd, &num_commit, sizeof(int));

    printf("num_segs=%d, name_length=%d, real_segname=%s, mods=%d, num_commit=%d \n", num_segs, name_length, real_segname, mods, num_commit);

    close(readfd);
    return 0;
}

Here's my output, as you can see num_commit is overwritten by the mods value:

num_segs=10, name_length=7, real_segname=testfil, mods=200, num_commit=200

War es hilfreich?

Lösung

This is my answer to my original question. The code below will always write the number of commits at the end of the file. Whenever new entries are written to the file, I make sure it will overwrite the last number of commits and append new number of commits at the end. This way will increment the number of commits and maintain only one copy of num_commit always at the end of the file.

int main()
{
    int name_length;
    char pathFile[MAX_PATHNAME_LEN];
    sprintf(pathFile, "my_log2.bin");
    int filedescriptor = open(pathFile, O_RDWR | O_CREAT, 0777);

    int num_segs = 10;
    int mods = 200;
    const char *segname = "testfil";
    char real_segname[128];
    strcpy(real_segname, segname); /* in my real program segname is passed into the function */

    int i;
    for (i = 1; i <= 100; i++)
    {
        if (i > 1)
        {
            lseek(filedescriptor, -sizeof(int), SEEK_END);  /* overwrite the last num_commit */
        }
        write(filedescriptor, &num_segs, sizeof(int));
        name_length = strlen(real_segname);
        write(filedescriptor, &name_length, sizeof(int));
        write(filedescriptor, real_segname, name_length);
        write(filedescriptor, &mods, sizeof(int));
        write(filedescriptor, &i, sizeof(int));  /* number of commits */
    }
    close(filedescriptor);

    /* now read back the file */
    int readfd = open(pathFile, O_RDONLY);
    lseek(readfd, -sizeof(int), SEEK_END);     /* read the number of commit first from the end of the file */

    int num_commit;
    read(readfd, &num_commit, sizeof(int));
    printf("num_commit = %d \n", num_commit);

    lseek(readfd, 0, SEEK_SET);  /* start reading from the beginning of the file*/
    int a, b, m;
    char *name;

    for (i = 0; i < num_commit; i++)
    {
        read(readfd, &a, sizeof(int));
        read(readfd, &b, sizeof(int));
        name = malloc(b);
        read(readfd, name, b);
        read(readfd, &m, sizeof(int));
        printf("commit# = %d, num_segs=%d, name_length=%d, real_segname=%s, mods=%d \n", i+1, a, b, name, m);

        free(name);
        name = NULL;
    }
    close(readfd);
    return 0;
}

As an alternative, I also tested maintaining the num_commit at the beginning of the file, which is a lot easier/less mind-twisting than using SEEK_END:

#define MAX_PATHNAME_LEN 256

int main()
{
    int commit_times = 10;

    char pathFile[MAX_PATHNAME_LEN];
    sprintf(pathFile, "my_log2.bin");
    int filedescriptor = open(pathFile, O_RDWR | O_CREAT, 0777);

    int num_segs = 10;
    int mods = 200;
    const char *segname = "testfil";
    char real_segname[128];
//    strncpy(real_segname, segname, sizeof(real_segname));
    strcpy(real_segname, segname);

    lseek(filedescriptor, 0, SEEK_SET);  /* write commit_times always at the beginning of the file */
    write(filedescriptor, &commit_times, sizeof(int));

    lseek(filedescriptor, sizeof(int), SEEK_SET);  /* start writing after num_commit value */
    write(filedescriptor, &num_segs, sizeof(int));
    int name_length = strlen(real_segname);
    write(filedescriptor, &name_length, sizeof(int));
    write(filedescriptor, real_segname, name_length);

    write(filedescriptor, &mods, sizeof(int));

    commit_times++;
    lseek(filedescriptor, 0, SEEK_SET);     /* update the commit_times at the beginning of the file */
    write(filedescriptor, &commit_times, sizeof(int));

    close(filedescriptor);

    /* now read back the file */
    int readfd = open(pathFile, O_RDONLY);

    int num_commit;
    read(readfd, &num_commit, sizeof(int));
    read(readfd, &num_segs, sizeof(int));
    read(readfd, &name_length, sizeof(int));
    read(readfd, real_segname, name_length);
    read(readfd, &mods, sizeof(int));


    printf("num_segs=%d, name_length=%d, real_segname=%s, mods=%d, num_commit=%d \n", num_segs, name_length, real_segname, mods, num_commit);

    close(readfd);




    return 0;
}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top