Некоторые текстовые редакторы Linux при отображении текстовых файлов Windows ставят в конце каждой строки обозначение ^M
— символ возврата каретки. В Emacs такие файлы отображаются правильно, но в строке режима появляется запись (DOS)
. Многие Windows-редакторы, например Notepad (Блокнот), показывают содержимое текстовых файлов Linux в виде одной длинной строки, так как предполагают наличие в конце строки символа возврата каретки.
Если программа читает текстовые файлы, сгенерированные Windows-программами, желательно менять последовательность '\r\n'
одним символом новой строки. Точно так же при записи текстовых файлов, которые будут читаться Windows-программами, нужно менять одиночные символы новой строки комбинациями '\r\n'
.
В листинге Б.4 демонстрируется применение функции read()
. Программа отображает шестнадцатиричный дамп файла, заданного в командной строке. В каждой строке показано смещение от начала файла, а затем — следующие 16 байтов.
Листинг Б.4. ( hexdump.c ) Отображение шестнадцатеричного дампа файла
#include
#include
#include
#include
#include
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);
/* Чтение данных из файла по одному блоку за раз. Чтение
продолжается до тех пор, пока размер очередной порции байтов
не окажется меньше размера буфера. Это свидетельствует
о достижении конца буфера. */
do {
/* чтение следующей строки байтов. */
bytes_read = read(fd, buffer, sizeof(buffer));
/* Отображение смещения, а затем самих байтов. */
printf("0x%06x : ", offset);
for (i = 0; i < bytes_read; ++i)
printf("%02x ", buffer[i]);
printf("\n");
/* Вычисление позиции в файле. */
offset += bytes_read;
}
while (bytes_read == sizeof(buffer));
/* Конец работы. */
close(fd);
return 0;
}
Ниже показаны результаты работы программы. Она выводит дамп самой себя.
% ./hexdump hexdump
0x000000 : 7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00
0x000010 : 02 00 03 00 01 00 00 00 c0 B3 04 0B 34 00 00 00
0x000020 : e8 23 00 00 00 00 00 00 34 00 20 00 06 00 28 00
0x000030 : 1d 00 1a 00 06 00 00 00 34 00 00 00 34 80 04 08
...
Эти результаты могут быть разными в зависимости от того, какой компилятор применялся и какие флаги компиляции были установлены.
Б.1.5. Перемещение по файлу
В файловом дескрипторе запоминается текущая позиция в файле. При чтении или записи данных указатель текущей позиции перемещается на то количество байтов, которое было прочитано или записано. Но иногда нужно осуществлять простое перемещение по файлу (позиционирование). Например, может потребоваться вернуться в начало файла и прочитать его заново, не открывая повторно.
Позиционирование указателя текущей позиции файла осуществляет функция lseek()
. Она принимает дескриптор файла и два дополнительных аргумента, определяющих новую позицию указателя.
■ Если третий аргумент равен SEEK_SET
, функция lseek()
интерпретирует второй аргумент как смещение (в байтах) от начала файла.
■ Если третий аргумент равен SEEK_CUR
, функция lseek()
интерпретирует второй аргумент как смещение (положительное или отрицательное) от текущей позиции.
■ Если третий аргумент равен SEEK_END
, функция lseek()
интерпретирует второй аргумент как смещение (в байтах) от конца файла.
Функция lseek()
возвращает смещение новой позиции от начала файла. Тип этого значения — off_t
. В случае ошибки возвращается -1. Функция неприменима к файлам некоторых типов, например к сокетам.
Если требуется узнать текущую позицию файла, задайте смещение 0:
off_t position = lseek(free_descriptor, 0, SEEK_CUR);
ОС Linux позволяет перемещать указатель текущей позиции за пределы файла. Обычно, если текущая позиция находится за концом файла и выполняется операция записи, операционная система автоматически увеличивает файл, чтобы вместить в него новые данные. "Промежуток" между старым признаком конца файла и указателем текущей позиции не записывается на диск. Linux лишь помечает его длину. Если впоследствии попытаться прочесть файл, окажется, что данный промежуток заполнен нулевыми байтами.
Благодаря данной особенности функции lseek()
можно создавать файлы огромного размера, практически не занимающие места на диске. Это продемонстрировано в листинге Б.5. В качестве аргументов командной строки программа принимает имя файла и требуемый размер в мегабайтах. Программа создает файл, перемещается с помощью функции lseek()
на нужное расстояние и записывает нулевой байт, после чего закрывает файл.
Читать дальше