Что такое функция fseek в C/C++?

Ответ

fseek — это функция стандартной библиотеки C (объявленная в <cstdio>), которая изменяет позицию указателя файлового потока (FILE*) для последующих операций чтения или записи. В C++ её использование оправдано при работе с унаследованным C-кодом или для низкоуровневых операций с файлами.

Сигнатура:

int fseek(FILE *stream, long int offset, int origin);

Параметры:

  1. stream — указатель на файловый поток.
  2. offset — смещение в байтах. Может быть отрицательным для перемещения назад.
  3. origin — точка отсчёта для смещения. Может принимать одно из трёх значений:
    • SEEK_SET — начало файла.
    • SEEK_CUR — текущая позиция указателя в файле.
    • SEEK_END — конец файла.

Возвращаемое значение: 0 в случае успеха, ненулевое значение (обычно -1) в случае ошибки.

Пример: чтение данных из середины файла

#include <cstdio>
#include <iostream>

int main() {
    FILE* pFile = std::fopen("data.bin", "rb");
    if (!pFile) {
        std::perror("Ошибка открытия файла");
        return 1;
    }

    // Перемещаем указатель на 100 байт от начала файла
    if (std::fseek(pFile, 100, SEEK_SET) != 0) {
        std::perror("Ошибка fseek");
        std::fclose(pFile);
        return 1;
    }

    char buffer[50];
    std::size_t bytesRead = std::fread(buffer, 1, sizeof(buffer), pFile);
    std::cout << "Прочитано " << bytesRead << " байт.n";

    std::fclose(pFile);
    return 0;
}

Важные замечания и ограничения:

  • Размер файла: Тип long int для смещения может быть недостаточным для файлов размером >2 ГБ. В POSIX-системах используйте fseeko с off_t, в Windows — _fseeki64 с __int64.
  • Потоки без произвольного доступа: fseek не работает с потоками, которые не поддерживают произвольный доступ (например, pipes, терминалы, сетевые сокеты).
  • Буферизация: При переключении между чтением и записью после fseek может потребоваться вызов fflush или функции позиционирования.
  • В C++: Для типобезопасного и объектно-ориентированного подхода предпочтительнее использовать потоки (std::fstream) и методы seekg/seekp.

Ответ 18+ 🔞

Э, слушай, вот тебе история про fseek. Представь, что файл — это огромная лента, а ты стоишь с каким-то хуем в руках, который умеет только читать или писать прямо перед собой. Так вот, fseek — это команда «отступи на столько-то шагов отсюда или отсюда». Проще говоря, функция, которая двигает этот самый указатель внутри файлового потока (FILE*), чтобы ты мог читать или писать не с начала, а откуда захочешь. В C++ её юзают, когда нужно поковыряться в старом коде или сделать что-то низкоуровневое, где новые плюшки с потоками — это овердохуища мороки.

Как она выглядит:

int fseek(FILE *stream, long int offset, int origin);

Что ей надо скормить:

  1. stream — это сам поток, тот самый файл, который ты открыл.
  2. offset — это сколько байтов отпрыгнуть. Можешь прыгнуть назад, если число отрицательное — хитрая жопа, да?
  3. origin — а это точка, от которой прыгаешь. Вариантов всего три, ёпта:
    • SEEK_SET — от начала файла. Классика.
    • SEEK_CUR — от того места, где стоишь сейчас.
    • SEEK_END — от конца файла. Полезно, когда нужно в хвост залезть.

Вернёт она: нолик, если всё заебись, и какую-то хуйню (обычно -1), если всё пошло по пизде.

Вот тебе живой пример, как прочитать кусок из середины файла:

#include <cstdio>
#include <iostream>

int main() {
    FILE* pFile = std::fopen("data.bin", "rb");
    if (!pFile) {
        std::perror("Ошибка открытия файла");
        return 1;
    }

    // Двигаемся на 100 байт от начала, будто хуй с горы скатился
    if (std::fseek(pFile, 100, SEEK_SET) != 0) {
        std::perror("Ошибка fseek");
        std::fclose(pFile);
        return 1;
    }

    char buffer[50];
    std::size_t bytesRead = std::fread(buffer, 1, sizeof(buffer), pFile);
    std::cout << "Прочитано " << bytesRead << " байт.n";

    std::fclose(pFile);
    return 0;
}

А теперь, чувак, лови важные подводные камни, об которые можно ебушки-воробушки разбиться:

  • Большие файлы — большие проблемы: Тип long int для смещения — это прошлый век. Если файл больше 2 ГБ, эта хуйня может накрыться медным тазом. На нормальных системах (POSIX) ищи fseeko, а на Винде — _fseeki64. Доверия к старому fseek с гигабайтами — ебать ноль.
  • Не все потоки гибкие: Попробуй сделать fseek на потоке из сети или пайпа — получишь пиздопроебибну. Эта функция только для файлов, где можно туда-сюда прыгать.
  • Буферы всё портят: Если ты только что писал, а потом решил сделать fseek и почитать, не забудь про fflush. А то буфер не сбросится, и ты будешь читать какую-то хуйню, а не то, что записал. Волнение ебать!
  • В C++ есть варианты круче: Если пишешь на плюсах и не приперло к сишному API, лучше юзай std::fstream с его seekg и seekp. Это типобезопасно и по-человечески. А fseek — это как ебать копать: работает, но есть инструменты поудобнее.