Чтение онлайн

на главную - закладки

Жанры

Linux программирование в примерах
Шрифт:

4.5. Произвольный доступ: перемещения внутри файла

До сих пор мы обсуждали последовательный ввод/вывод, при котором данные читаются или записываются с начала файла и продолжаются до его конца. Часто это все, что требуется программе. Однако, возможно осуществление произвольного ввода/вывода; т.е. читать данные из произвольного положения в файле без необходимости предварительного чтения всего, что находится перед этим местом.

Смещение дескриптора файла является положением внутри открытого

файла, начиная с которого будет осуществляться следующая операция чтения или записи. Программа устанавливает смещение с помощью системного вызова
lseek
:

#include <sys/types.h> /* для off_t; POSIX */

#include <unistd.h> /* объявления lseek и значений whence */

off_t lseek(int fd, off_t offset, int whence);

Тип

off_t
(тип смещения) является знаковым целым, представляющим позиции байтов (смещений от начала) внутри файла. На 32-разрядных системах тип представлен обычно как
long
. Однако, многие современные системы допускают очень большие файлы, в этом случае
off_t
может быть более необычным типом, таким, как C99
int64_t
или какой-нибудь другой расширенный тип.
lseek
принимает три следующих аргумента.

int fd

Дескриптор открытого файла.

off_t offset

Позиция, в которую нужно переместиться. Интерпретация этого значения зависит от параметра

whence
.
offset
может быть положительным или отрицательным; отрицательные значения перемещают к началу файла; положительные значения перемещают к концу файла.

int whence

Описывает положение в файле, относительно которого отсчитывается

offset
. См. табл. 4.4.

Таблица 4.4. Значения

whence
для
lseek

Именованная константа Значение Комментарий
SEEK_SET
0
offset
абсолютно, т.е. относительно начала файла
SEEK_CUR
1
offset
относительно текущей позиции в файле
SEEK_END
2
offset
относительно конца файла.

Большое количество старого кода использует числовые значения, приведенные в табл. 4.4. Однако, любой новый код, который вы пишете, должен использовать символические имена, значение которых более ясно.

Смысл значений и их действие на положение в файле показаны на рис. 4.1. При условии, что файл содержит 3000 байтов и что перед каждым вызовом

lseek
текущим является
смещение 2000 байтов, новое положение после каждого вызова будет следующим.

Рис. 4.1. Смещения для

lseek

Отрицательные смещения относительно начала файла бессмысленны; они вызывают ошибку «недействительный параметр».

Возвращаемое значение является новым положением в файле. Поэтому, чтобы получить ваше текущее местоположение в файле, используйте

off_t curpos;

...

curpos = lseek(fd, (off_t)0, SEEK_CUR);

Буква

l
в
lseek
означает
long
.
lseek
был введен в V7 Unix, когда размеры файлов были увеличены; в V6 был простой системный вызов
seek
. В результате большое количество старой документации (и кода) рассматривает параметр offset как имеющий тип
long
, и вместо приведения к типу
off_t
довольно часто можно видеть суффикс L в константных значениях смешений:

curpos = lseek(fd, 0L, SEEK_CUR);

На системах с компилятором стандартного С, где

lseek
объявлена с прототипом, такой старый код продолжает работать, поскольку компилятор автоматически преобразует 0L из
long
в
off_t
, если это различные типы.

Одной интересной и важной особенностью

lseek
является то, что она способна устанавливать смещение за концом файла. Любые данные, которые впоследствии записываются в это место, попадают в файл, но с образованием «интервала» или «дыры» между концом предыдущих данных файла и началом новых данных. Данные в промежутке читаются, как если бы они содержали все нули.

Следующая программа демонстрирует создание дыр. Она записывает три экземпляра

struct
в начало, середину и дальний конец файла. Выбранные смешения (строки 16–18, третий элемент каждой структуры) произвольны, но достаточно большие для демонстрации особенности:

1 /* ch04-holes.c --- Демонстрация lseek и дыр в файлах. */

2

3 #include <stdio.h> /* для fprintf, stderr, BUFSIZ */

4 #include <errno.h> /* объявление errno */

5 #include <fcntl.h> /* для flags для open */

6 #include <string.h> /* объявление strerror */

7 #include <unistd.h> /* для ssize_t */

8 #include <sys/types.h> /* для off_t, etc. */

9 #include <sys/stat.h> /* для mode_t */

10

11 struct person {

12 char name[10]; /* имя */

13 char id[10]; /* идентификатор */

Поделиться:
Популярные книги

Газлайтер. Том 28

Володин Григорий Григорьевич
28. История Телепата
Фантастика:
боевая фантастика
аниме
попаданцы
5.00
рейтинг книги
Газлайтер. Том 28

Чужое наследие

Кораблев Родион
3. Другая сторона
Фантастика:
боевая фантастика
8.47
рейтинг книги
Чужое наследие

Идеальный мир для Лекаря 21

Сапфир Олег
21. Лекарь
Фантастика:
фэнтези
юмористическое фэнтези
аниме
5.00
рейтинг книги
Идеальный мир для Лекаря 21

Имя нам Легион. Том 7

Дорничев Дмитрий
7. Меж двух миров
Фантастика:
боевая фантастика
рпг
аниме
5.00
рейтинг книги
Имя нам Легион. Том 7

Двойник Короля

Скабер Артемий
1. Двойник Короля
Фантастика:
попаданцы
аниме
фэнтези
фантастика: прочее
5.00
рейтинг книги
Двойник Короля

Бастард Императора. Том 12

Орлов Андрей Юрьевич
12. Бастард Императора
Фантастика:
попаданцы
аниме
фэнтези
фантастика: прочее
5.00
рейтинг книги
Бастард Императора. Том 12

Эволюционер из трущоб. Том 7

Панарин Антон
7. Эволюционер из трущоб
Фантастика:
попаданцы
аниме
фэнтези
фантастика: прочее
5.00
рейтинг книги
Эволюционер из трущоб. Том 7

Душелов. Том 6

Faded Emory
6. Внутренние демоны
Фантастика:
постапокалипсис
ранобэ
хентай
фэнтези
5.00
рейтинг книги
Душелов. Том 6

Запасная дочь

Зика Натаэль
Фантастика:
фэнтези
6.40
рейтинг книги
Запасная дочь

Последний Паладин. Том 6

Саваровский Роман
6. Путь Паладина
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Последний Паладин. Том 6

Купец из будущего

Чайка Дмитрий
1. Третий Рим
Фантастика:
попаданцы
5.25
рейтинг книги
Купец из будущего

Правильный лекарь. Том 6

Измайлов Сергей
6. Неправильный лекарь
Фантастика:
городское фэнтези
аниме
фэнтези
попаданцы
5.00
рейтинг книги
Правильный лекарь. Том 6

Магия чистых душ

Шах Ольга
Любовные романы:
любовно-фантастические романы
5.40
рейтинг книги
Магия чистых душ

Идеальный мир для Лекаря 27

Сапфир Олег
27. Лекарь
Фантастика:
аниме
фэнтези
5.00
рейтинг книги
Идеальный мир для Лекаря 27