C: lseek () связанный вопрос - PullRequest
0 голосов
/ 04 апреля 2010

Я хочу написать некоторый фиктивный текст в файл (текст "helloworld" в файле с именем helloworld ), но не с самого начала. Я думал о lseek () функция.

Если я использую следующий код ( отредактировано ):

#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <stdlib.h>
#include <stdio.h>

#define fname "helloworld"
#define buf_size 16

int main(){

    char buffer[buf_size];
    int fildes,
        nbytes;
    off_t ret;

    fildes = open(fname, O_CREAT | O_TRUNC | O_WRONLY, S_IRUSR | S_IWUSR);
    if(fildes < 0){
        printf("\nCannot create file + trunc file.\n");
    }
//modify offset
    if((ret = lseek(fildes, (off_t) 10, SEEK_END)) < (off_t) 0){
        fprintf(stdout, "\nCannot modify offset.\n");
    }
    printf("ret = %d\n", (int)ret);

    if(write(fildes, fname, 10) < 0){
        fprintf(stdout, "\nWrite failed.\n");
    }

    close(fildes);

    return (0);
}

, он хорошо компилируется и работает без каких-либо явных ошибок. Тем не менее, если я:

cat helloworld

Вывод не тот, который я ожидал, но:

helloworld
Can

Откуда исходит "Can" и где мои пустые места?

Должен ли я ожидать "нули" вместо пробелов? Если я пытаюсь открыть helloworld с помощью gedit, возникает ошибка, сообщающая, что кодировка символов файла неизвестна.

ПОСЛЕДНЕЕ РЕДАКТИРОВАНИЕ : После того, как я отредактировал свою программу с подходящим буфером для записи, а затем снова скомпилировал / запустил, файл «helloworld» все еще не может быть открыт с помощью gedit. strong text

ПОЗЖЕ РЕДАКТИРОВАТЬ Теперь я понимаю проблему. Я добавил в код следующее:

fildes = open(fname, O_RDONLY);
if(fildes < 0){
    printf("\nCannot open file.\n");
}

while((nbytes = read(fildes, c, 1)) == 1){
    printf("%d ", (int)*c);     
}

А теперь вывод:

0 0 0 0 0 0 0 0 0 0 104 101 108 108 111 119 111 114 108 100

Моя проблема заключалась в том, что я ожидал пробелы (32) вместо нулей (0).

Ответы [ 3 ]

2 голосов
/ 04 апреля 2010

В этом вызове функции write(fildes, fname, buf_size), fname имеет 10 символов (плюс завершающий символ '\ 0', но вы говорите функции записать 16 байтов. Кто знает, что в ячейках памяти после fname строка.

Кроме того, я не уверен, что вы подразумеваете под "где мои пустые места?".

1 голос
/ 04 апреля 2010

Помимо ожидания, что нули равны пробелам, исходная проблема действительно заключалась в записи больше, чем длина строки "helloworld". Чтобы избежать такой проблемы, я предлагаю позволить компилятору рассчитать для вас длину ваших константных строк:

    write(fildes, fname, sizeof(fname) - 1)

- 1 происходит из-за символа NUL (ноль, \0), который используется для завершения строк в стиле C, и sizeof просто возвращает размер массива, который содержит строку. Из-за этого вы не можете использовать sizeof для вычисления фактической длины строки во время выполнения, но она отлично работает для констант времени компиляции.

«Can», который вы видели в своем первоначальном тесте, почти наверняка стал началом одной из "\nCannot" строк в вашем коде; после записи 11 байтов в "helloworld\0" вы продолжили записывать оставшиеся байты из того, что следовало за ним в памяти, что оказалось следующей строковой константой. (Вопрос теперь был изменен, чтобы записать 10 байтов, но первоначально опубликованная версия написала 16.)

Наличие символов NUL (= ноль, '\0') в текстовом файле действительно может привести к тому, что некоторые (но не все) текстовые редакторы будут рассматривать двоичные данные файла вместо текста и, возможно, откажутся открывать его. Текстовый файл должен содержать только текст, а не управляющие символы.

1 голос
/ 04 апреля 2010

Ваш размер buf_size не соответствует длине имени. Он читает мимо буфера и, следовательно, получает более или менее случайные байты, которые случайно оказались за строкой в ​​памяти.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...