如何在Linux上使用O_APPEND模式的Open函数向C文件追加内容?

6
这是作业的一部分。我在作业中无法运行,于是我抽出一小段代码并开始尝试弄清楚问题所在。
在Linux下使用C语言,我正在尝试打开/创建一个文本文件,向其中写入一些内容,然后关闭它,在读/写和追加模式下重新打开它,最后在文件末尾添加任何内容(在这个示例中,为字符串“,dude”)。但是没有添加任何内容,而且写方法也没有抛出错误。我不确定出了什么问题。
以下是代码:
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <errno.h>

#define BUFFSIZE 4096

int main(){
    mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;

    int fd = open("tempfile.txt", O_RDWR | O_CREAT, mode);

    char buf[BUFFSIZE] = {'t', 'h', 'y', ' ', 'f', 'a', 'l', 'l'};

    size_t n = sizeof(buf);
    if(write (fd, buf, n) < 0){
        printf("Error in write\n");
        printf("%s", strerror(errno));
        return 1;
    }

    close(fd);

    int fd2 = open("tempfile.txt", O_RDWR | O_APPEND);

    printf("appending dude:\n");
    char buf2[6] = {',', ' ', 'd', 'u', 'd', 'e'};
    size_t p = sizeof(buf2);
    if(write (fd2, buf2, p) < 0){
        printf("Error in write\n");
        printf("%s", strerror(errno));
        return 1;
    }

    char buf3[BUFFSIZE];
    lseek(fd2, 0, SEEK_SET);
    if(read (fd2, buf3, BUFFSIZE) < 0){
        printf("Error in read\n");
        printf("%s", strerror(errno));
        return 2;
    }
    int i;
    for (i = 0; i < strlen(buf3); ++i){
        printf("%c", buf3[i]);
    }
    printf("\n");

    close(fd2);

    return 0;
}

我试图通过尝试不同的组合来排除严格的权限问题,将模式变量更改为S_IRWXU | S_IRWXG | S_IRWXO,在第二个打开语句中传递模式作为第三个参数,仅在第二个打开语句中以追加模式打开文件,将追加模式作为第三个参数传递给第二个打开语句等等。
我所能做到的最好的方法是以RDWR模式打开它,而没有APPEND模式,然后直接覆盖现有文本...但这不是我想要的。请注意,我知道像lseek这样的东西,但这里的目的只是使用追加模式将文本添加到文件末尾。我不想使用lseek。
从这段话中有什么线索吗?我肯定有一些显而易见的东西我不理解。
非常感谢。
4个回答

4

好的,我刚刚尝试了您的程序,对于出错原因有了一些想法。

基本上,它是能够工作的,但存在一个问题。当您首次将“thy fall”写入文件时,您使用了一个大小为4096字节的char数组,并将整个数组写入文件中。这意味着您正在写入“thy fall”,后面跟随着4088个不相关的字符。稍后,当您添加内容时,您从第4097个位置开始添加。这可能不是您打算做的。

如果您只是简单地使用cat命令查看创建的文件,您会看到预期输出:“thy fall, dude”。但是,在您的代码中完全读取它时,您只读取了4096个字符。因此,“,dude”部分从未被读取,这就是为什么您的程序从未输出它的原因。

我的解决方案是,您需要更改数组大小。在读取时,可以分块读取,比如每次读取100或1000个字符,直到遇到EOF(read函数会返回-1)。


好的。你能否顺便添加一个如何使用cat的例子吗?(我对C有点陌生,但会去查一下...) - Deranger
1
“cat” 是任何 Linux shell 上都可用的命令。如果您使用的是 bash,只需打开终端,切换到程序所在的目录,然后执行 “cat tempfile.txt” 命令即可。 - Nikhil
好的 - 现在我已经把它搞定了。我认为你和Rohan都是正确的,但是像Rohan建议的那样添加空字符来终止数组并使用strlen而不是sizeof给了我我想要的确切结果。所以我会点赞这两个答案,但选择Rohan的作为实际回答我的问题。非常感谢你们的帮助! - Deranger

3

只有一个小错误,你需要将sizeof函数更改为strlen,因为sizeof函数将返回数组的大小,而strlen函数只返回存储在数组中的字符串的长度!


3
尝试写入的字节数不正确,
char buf[BUFFSIZE] = {'t', 'h', 'y', ' ', 'f', 'a', 'l', 'l'};
size_t n = sizeof(buf);
if(write (fd, buf, n) < 0){

你应该做的是

char buf[BUFFSIZE] = {'t', 'h', 'y', ' ', 'f', 'a', 'l', 'l', '\0'};
size_t n = strlen(buf); //use strlen 
if(write (fd, buf, n) < 0){

类似地,对于其他的写入和读取操作也要这样做。如果你在文件中没有写入'\0'来终止字符串,那么当你从文件中读取数据时,你就无法得到它。

在读取时,应该尝试读取整个文件,也就是直到你得到了EOF


-1
这是已经纠正的代码,你还需要使用O_CREAT标志来最初创建文件。
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <errno.h>

main()
{

int fd = open("tempfile.txt",O_CREAT|O_RDWR|O_APPEND);
        printf( "hello\n" );
        char buf[] = {'t', 'h', 'y', ' ', 'f', 'a', 'l', 'l', '\0'};

    size_t n = strlen(buf);

    if(!write(fd, buf, n)){
        printf("Error in write\n");
        printf("%s", strerror(errno));
        return 1;
    }

    close(fd);

    int fd2 = open("tempfile.txt", O_RDWR | O_APPEND);

    printf("appending dude:\n");
    char buf2[] = {',', ' ', 'd', 'u', 'd', 'e', '\0'};
    size_t p = sizeof(buf2);
    if(!write(fd2, buf2, p)){
        printf("Error in write\n");
        printf("%s", strerror(errno));
        return 1;
    }

    char buf3[n + p];
    lseek(fd2, 0, SEEK_SET);
    if(!read (fd2, buf3, (n + p) )){
        printf("Error in read\n");
        printf("%s", strerror(errno));
        return 2;
    }
    int i;
    for (i = 0; i < ( n + p ); ++i){
        printf("%c", buf3[i]);
    }
    printf("\n");
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接