Самьюэл Алекс
Шрифт:
/* Открытие файла для записи. Если файл существует, он
открывается в режиме добавления; в противном случае
файл создается. */
int fd =
open(filename. O_WRONLY | O_CREAT | O_APPEND, 0666);
/* Вычисление длины строки с меткой времени. */
size_t length = strlen(timestamp);
/* Запись метки времени в файл. */
write(fd, timestamp, length);
/* Конец работы. */
close(fd);
return 0;
}
Вот как работает программа:
% ./timestamp tsfile
% cat tsfile
The Feb 1 23:25:20 2001
% ./timestamp tsfile
% cat tsfile
Thu Feb 1 23:25:20 2001
Thu Feb 1 23:25:47 2001
Обратите внимание на то, что при первом вызове программы
timestamp
файл был создан, а при втором вызове — дополнен. Функция
write
возвращает число записанных байтов или -1, если произошла ошибка. Для некоторых типов файлов чисто фактически записанных байтов может оказаться меньше требуемого. Программа должна выявлять подобные случаи и вызывать функцию write
повторно, чтобы передать оставшуюся часть данных. Этот прием продемонстрирован в листинге Б.3. Но иногда даже таких методов недостаточно. Например, если показанная функция будет записывать данные в сокет, в нее придется добавить код проверки того, не произошел ли в ходе операции записи разрыв соединения. Листинг Б.3. (write-all.c) Запись буфера
/* Запись указанного числа байтов (COUNT) из буфера BUFFER
в файл FD. В случае ошибки возвращается -1,
иначе -- число записанных байтов. */
ssize_t write_all(int fd, const void* buffer, size_t count) {
size_t left_to_write = count;
while (left_to_write > 0) {
size_t written = write(fd, buffer, count);
if (written == -1)
/* Произошла ошибка, завершаем работу. */
return -1;
else
/* подсчитываем число оставшихся байтов. */
left_to_write -= written;
}
/* Нельзя записать больше, чем COUNT байтов! */
assert(left_to_write == 0);
/* Число записанных байтов равно COUNT. */
return count;
}
Б.1.4. Чтение данных
Функция, осуществляющая чтение данных из файла, называется
read
. Подобно функции write
, она принимает дескриптор файла, указатель на буфер и счетчик числа извлекаемых байтов. Функция возвращает число прочитанных байтов или -1 в случае ошибки. Иногда читается меньше байтов, чем требовалось, если, например, в файле содержится недостаточно байтов. Чтение текстовых файлов DOS/Windows
В Linux-программах нередко приходится читать файлы, созданные в DOS или Windows. Важно понимать разницу между тем, как структурируются текстовые файлы в Linux и в DOS/Windows.
В Linux каждая строка текстового файла оканчивается символом новой строки. Он представляется символьной константой
'\n'
, ASCII-код которой равен 10. В Windows строки разделяются двухсимвольной комбинацией символ возврата каретки (константа '\r'
, ASCII-код 13), за которым идет символ новой строки. Некоторые текстовые редакторы Linux при отображении текстовых файлов Windows ставят в конце каждой строки обозначение
^M
— символ возврата каретки. В Emacs такие файлы отображаются правильно, но в строке режима появляется запись (DOS)
. Многие Windows-редакторы, например Notepad (Блокнот), показывают содержимое текстовых файлов Linux в виде одной длинной строки, так как предполагают наличие в конце строки символа возврата каретки. Если программа читает текстовые файлы, сгенерированные Windows-программами, желательно менять последовательность
'\r\n'
одним символом новой строки. Точно так же при записи текстовых файлов, которые будут читаться Windows-программами, нужно менять одиночные символы новой строки комбинациями '\r\n'
. В листинге Б.4 демонстрируется применение функции
read
. Программа отображает шестнадцатиричный дамп файла, заданного в командной строке. В каждой строке показано смещение от начала файла, а затем — следующие 16 байтов. Листинг Б.4. (hexdump.c) Отображение шестнадцатеричного дампа файла
#include <fcntl.h>
#include <stdio.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
int main(int argc, char* argv[]) {
unsigned char buffer[16];
size_t offset = 0;
size_t bytes_read;
int i;
/* Открытие файла для чтения. */
int fd = open(argv[1], O_RDONLY);
/* Чтение данных из файла по одному блоку за раз. Чтение
продолжается до тех пор, пока размер очередной порции байтов