如何在C中追加到文件,在Linux上使用O_APPEND模式打开?

时间:2013-10-03 05:02:28

标签: c linux file file-io append

这是家庭作业的一部分。好吧,我的作业无法完成工作,所以我已经拉出了一个小片段并开始用它来弄清楚什么是错的。

在C语言的Linux上我试图打开/创建一个文本文件,写一些东西,关闭它,以读/写和追加模式打开它,然后追加任何东西到它的结尾(在这个例子中,字符串",dude")。但是没有附加任何内容,但write方法也没有引发错误。我不确定是什么。

以下是代码:

#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,在我的第二个open语句中将模式作为第三个参数传递,只在第二个open语句中以append模式打开文件,在第二个open语句中将append模式作为第三个参数传递,等等。

我能做的最好的事情就是在没有APPEND模式的情况下在RDWR中打开它,然后直接在现有文本上书写......但这不是我想要的。请注意,我知道像lseek这样的东西,但这里的目的是严格使用追加模式将文本添加到文件的末尾。我不想lseek。

看到这个的任何线索?我确定有一些显而易见的东西,我只是不明白。

非常感谢。

4 个答案:

答案 0 :(得分:3)

好吧,我刚试过你的程序并知道出了什么问题。

基本上,它确实有效,但有一个小故障。当你第一次写下你的堕落&#34;在文件中,您使用char4096字节数组,并将整个数组写入文件。这意味着你正在写下你的堕落&#34;其次是4088个随机字符。之后,当你追加你时,你会在第4097位追加。这可能不是你想要做的。

如果你只是cat你创建的文件,你会看到预期的输出&#34;你的堕落,伙计&#34;。但是当您在代码中完全阅读它时,您只能阅读4096个字符。因此,&#34;,dude&#34;部分永远不会被读取,这就是为什么你的程序永远不会输出它。

我的解决方案,您需要更改阵列大小。阅读时,请阅读100或1000的块,直到您点击EOF(read将返回-1)。

答案 1 :(得分:2)

您尝试写入的字节数不正确,

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

答案 2 :(得分:1)

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

答案 3 :(得分:-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");
}