当read()时,写入文件描述符的write()消失

时间:2018-11-10 02:16:21

标签: c file-descriptor read-write lseek

所以我现在正在程序的服务器端工作,我想执行以下操作:

1)以读写模式打开文件

2)在文件末尾附加一个单词(WORD)

3)[我相信我已经把所有这部分都准备好了]打开管道,创建一个子进程,让它直接从文件(文件描述符)中读取,执行命令,并将结果发送到write /管道的输出。父进程从管道的读取/输入中读取信息,并将信息放入缓冲区以发送回客户端。

我遇到麻烦的是附加部分。我非常确定它会追加到文件中(在现有文本和WORD之间插入换行符),因为当我直接打开文本文件时,它就在那里。但是,当我尝试从缓冲区中打印它时,它不存在。我尝试在写入并重新打开后关闭文件描述符,但它不存在。我试过strcat而不是写文件描述符,它不存在。

  #define WORD "WORD"
  #define BUFFERLENGTH 512
  char buffer[BUFFERLENGTH];

  int fileDesc = open (filePath, O_RDWR|O_APPEND, 0660);
  if (fileDesc <= 0){
    write(clientDesc, ERRORMSG, BUFFERLENGTH);
    exit(EXIT_FAILURE);
  }

  read(fileDesc,buffer,BUFFERLENGTH);

  long length  = lseek(fileDesc,0,SEEK_END);
  int status  = write(fileDesc,WORD,sizeof(WORD)-1);

  read(fileDesc, buffer, BUFFER_LEN+1);
  printf("new text: %s\n", buffer); //WORD does not show up at the end of file as intended

我真的有误会吗?

也许我不完全了解open(),read(),write()和lseek()的工作原理,但是如果有人可以帮助我向我解释为什么这没有按预期进行,那将是非常重要的赞赏。在过去的一周里,我一直在为此苦苦挣扎,而我目前为寻找解决方案而打开的选项卡数量非常可悲。

1 个答案:

答案 0 :(得分:2)

write()通话之后,您将位于文件末尾,因此read()将无法读取任何内容。如果您希望能够从文件中读取任何内容,则需要lseek()到文件中的较早位置。

您应该检查read()的返回值(以及与此相关的几乎所有其他系统调用),并在出现错误的情况下使用perror()或类似的方法,这将对帮助您有所帮助了解当您看到意想不到的行为时发生了什么。

修改程序:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>

#define WORD "WORD"
#define BUFFERLENGTH 512

int main(void)
{
    char * filePath = "testfile.txt";
    char buffer[BUFFERLENGTH] = {0};

    // Open file.

    int fd = open(filePath, O_RDWR | O_APPEND, 0660);
    if (fd < 0) {
        perror("couldn't open file");
        return EXIT_FAILURE;
    }

    // Write word to end.

    int status = write(fd, WORD, strlen(WORD));
    if ( status < 0 ) {
        perror("couldn't write");
        return EXIT_FAILURE;
    }

    // Seek to start of file.

    long length = lseek(fd, 0, SEEK_SET);
    if ( length < 0 ) {
        perror("couldn't lseek");
        return EXIT_FAILURE;
    }

    // Read contents of file.

    status = read(fd, buffer, BUFFERLENGTH - 1);
    if ( status < 0 ) {
        perror("couldn't read");
        return EXIT_FAILURE;
    }

    // Print buffer.

    printf("file contents: %s\n", buffer);

    return 0;
}

产量:

paul@mac:scratch$ touch testfile.txt
paul@mac:scratch$ ./file
file contents: WORD
paul@mac:scratch$ ./file
file contents: WORDWORD
paul@mac:scratch$ ./file
file contents: WORDWORDWORD
paul@mac:scratch$ ./file
file contents: WORDWORDWORDWORD
paul@mac:scratch$

如果您只想实际查看新内容,则需要lseek()到文件开头以外的某个位置。由于成功的write()将返回写入的字节数,因此您可以使用此值从文件末尾向后偏移:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>

#define BUFFERLENGTH 512

int main(int argc, char * argv[])
{
    if ( argc < 2 ) {
        fprintf(stderr, "you need to enter a word argument\n");
        return EXIT_FAILURE;
    }

    char * filePath = "testfile.txt";
    char buffer[BUFFERLENGTH] = {0};

    // Open file.

    int fd = open(filePath, O_RDWR | O_APPEND, 0660);
    if ( fd < 0 ) {
        perror("couldn't open file");
        return EXIT_FAILURE;
    }

    // Write word to end.

    int status = write(fd, argv[1], strlen(argv[1]));
    if ( status < 0 ) {
        perror("couldn't write");
        return EXIT_FAILURE;
    }

    // Seek to point before last write.

    long length = lseek(fd, -status, SEEK_END);
    if ( length < 0 ) {
        perror("couldn't lseek");
        return EXIT_FAILURE;
    }

    // Read from there to end of file.

    status = read(fd, buffer, BUFFERLENGTH - 1);
    if ( status < 0 ) {
        perror("couldn't read");
        return EXIT_FAILURE;
    }

    // Print buffer.

    printf("new text: %s\n", buffer);

    return 0;
}

收益:

paul@mac:scratch$ rm testfile.txt
paul@mac:scratch$ touch testfile.txt
paul@mac:scratch$ ./file2 these
new text: these
paul@mac:scratch$ ./file2 are
new text: are
paul@mac:scratch$ ./file2 some
new text: some
paul@mac:scratch$ ./file2 words
new text: words
paul@mac:scratch$ cat testfile.txt
thesearesomewordspaul@mac:scratch$