c - 在 C 中的 write() 过程中更新文件末尾的数字

标签 c io lseek

我正在测试我的程序,以始终更新文件末尾的数字(num_commit)。该数字用于跟踪文件已写入的次数。我正在使用 lseek/SEEK_END,但我仍在尝试弄清楚它是如何工作的。我编写了以下代码来测试可能性,但 num_commit 似乎被覆盖了。我正在寻求有关正确方法的帮助:

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

这是我的输出,您可以看到 num_commit 被 mods 值覆盖:

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

最佳答案

这是我对原来问题的回答。下面的代码将始终在文件末尾写入提交数。每当新条目写入文件时,我确保它将覆盖最后的提交次数并在末尾附加新的提交次数。这种方式将增加提交次数,并始终在文件末尾只维护一份 num_commit 副本。

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;
}
<小时/>

作为替代方案,我还测试了在文件开头维护 num_commit ,这比使用 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;
}

关于c - 在 C 中的 write() 过程中更新文件末尾的数字,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23298504/

相关文章:

c - Windows中的 `fprintf()`和 `fscanf()`是否需要以文本模式打开文件

c - 如何在输出中获得 0?

java - 如何在java nio中创建多个监听同一端口的udp客户端?

c - 这个错误是什么意思 : "free(): double free detected in tcache 2"

c - 不透明函数调用在编译器优化中意味着什么?

c++ - 文件IO从文件中读取多种类型

java - 对于在 Java 中并行应用 MD5 哈希到一组文件的行为变化是否有解释?

c - Lseek SEEK_END 不工作?

c - 在 Linux 中用 C 打印最后 5 行文件

c - lseek() 尝试使用字节文件,但指针是 FILE 类型