Хрестоматия по программированию на Си в Unix

Электрик сделает подключение электрики в Кемерове и пригороде. Русский электрик. | Заказать - проекты металлоконструкций в Новокузнецке и пригороде на заказ.

Работа с файлами. Хрестоматия по программированию на Си в Unix - стр. 10


Напишите программу, которая находит в файле символ @ и выдает файл с этого места дважды. Указание: для запоминания позиции в файле используйте вызов lseek() позиционирование указателя чтения/записи:

long offset, lseek(); ... /* Узнать текущую позицию чтения/записи: * сдвиг на 0 от текущей позиции. lseek вернет новую * позицию указателя (в байтах от начала файла). */ offset = lseek(fd, 0L, 1); /* ftell(fp) */

А для возврата в эту точку:

lseek(fd, offset, 0); /* fseek(fp, offset, 0) */

По поводу lseek надо помнить такие вещи:

  • lseek(fd, offset, whence) устанавливает указатель чтения/записи на расстояние offset байт при whence:

    0 от начала файла RWptr = offset; 1 от текущей позиции RWptr += offset; 2 от конца файла RWptr = длина_файла + offset;

    Эти значения whence можно обозначать именами:

    #include <stdio.h>

    0 это SEEK_SET

    1 это SEEK_CUR

    2 это SEEK_END

  • Установка указателя чтения/записи - это виртуальная операция, т.е. реального подвода магнитных головок и вообще обращения к диску она не вызывает. Реальное движение головок к нужному месту диска произойдет только при операциях чтения/записи read()/write(). Поэтому lseek() - дешевая операция.
  • lseek() возвращает новую позицию указателя чтения/записи RWptr относительно начала файла (long смещение в байтах). Помните, что если вы используете это значение, то вы должны предварительно описать lseek как функцию, возвращающую длинное целое: long lseek();
  • Аргумент offset должен иметь тип long (не ошибитесь!).
  • Если поставить указатель за конец файла (это допустимо!), то операция записи write() сначала заполнит байтом '\0' все пространство от конца файла до позиции указателя; операция read() при попытке чтения из-за конца файла вернет "прочитано 0 байт". Попытка поставить указатель перед началом файла вызовет ошибку.
  • Вызов lseek() неприменим к pipe и FIFO-файлам, поэтому попытка сдвинуться на 0 байт выдаст ошибку:

    /* это стандартная функция */ int isapipe(int fd){ extern errno; return (lseek(fd, 0L, SEEK_CUR) < 0 && errno == ESPIPE); }




    - Начало -  - Назад -  - Вперед -