Write () в дескриптор файла исчезает при чтении () - PullRequest
0 голосов
/ 10 ноября 2018

Итак, я сейчас работаю на стороне сервера моей программы и хочу сделать следующее:

1) открыть файл в режиме чтения / записи

2) добавить слово (WORD) в конец файла

3) [Я полагаю, у меня уже есть вся эта часть] открыть канал, создать дочерний процесс, прочитать его непосредственно из файла (дескриптор файла), выполнить команду и отправить результат в запись / выход трубы. Родительский процесс считывает данные из канала чтения / ввода и помещает информацию в буфер для отправки обратно клиенту.

У меня проблемы с добавлением. Я почти уверен, что он добавляется в файл (с новой строкой между существующим текстом и моим 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 голосов
/ 10 ноября 2018

После вашего 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$ 
...