fseek для 32-разрядного беззнакового смещения

Я читаю формат файла (TIFF), который имеет 32-битные беззнаковые смещения от начала файла.

К сожалению, прототип для fseek, обычный способ, который я хотел бы использовать для конкретного смещения файла, это:

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

поэтому смещение подписано. Как я должен справиться с этой ситуацией? Должен ли я использовать другую функцию для поиска?

Вы можете попробовать использовать lseek64() ( lseek64() страница )

  #define _LARGEFILE64_SOURCE /* See feature_test_macros(7) */ #include  #include  off64_t lseek64(int fd, off64_t offset, int whence); 

С

  int fd = fileno (stream); 

Примечания от GNU C lib – настройка положения файла дескриптора

Эта функция аналогична функции lseek. Разница заключается в том, что параметр offset имеет тип off64_t вместо off_t, что позволяет на 32-битных машинах адресовать файлы размером более 2 ^ 31 байт и до 2 ^ 63 байта. Файлы-дескрипторы файла должны быть открыты с использованием open64, так как в противном случае большие смещения, возможно, с off64_t приведут к ошибкам с дескриптором в малом режиме файла.

Когда исходный файл скомпилирован с _FILE_OFFSET_BITS == 64 на 32-битной машине, эта функция действительно доступна под именем lseek и поэтому прозрачно заменяет 32-битный интерфейс.

О fd и stream , из streamов и дескрипторов файлов

Поскольку streamи реализованы в терминах файловых дескрипторов, вы можете извлечь дескриптор файла из streamа и выполнить операции низкого уровня непосредственно в дескрипторе файла. Вы также можете сначала открыть соединение в качестве файлового дескриптора, а затем создать stream, связанный с этим файловым дескриптором.

Изучив этот вопрос более глубоко и, учитывая другие комментарии и ответы (спасибо), я считаю, что самый простой способ – сделать два запроса, если смещение больше, чем 2147483647 байт. Это позволяет мне сохранять смещения как uint32_t и продолжать использовать fseek . Таким образом, код позиционирования выглядит следующим образом:

 // note: error handling code omitted uint32_t offset = ... (whatever it is) if( offset > 2147483647 ){ fseek( file, 2147483647, SEEK_SET ); fseek( file, (long int)( offset - 2147483647 ), SEEK_CUR ); } else { fseek( file, (long int) offset, SEEK_SET ); } 

Проблема с использованием 64-битных типов заключается в том, что код может работать в 32-битной архитектуре (между прочим). Существует функция fsetpos которая использует структуру fpos_t для управления сколь угодно большими смещениями, но это приносит с собой ряд сложностей. Хотя fsetpos может иметь смысл, если я действительно использую смещения произвольно большого размера, так как я знаю, что наибольшее возможное смещение – uint32_t, тогда двойной поиск удовлетворяет эту потребность.

Обратите внимание, что это решение позволяет обрабатывать все файлы TIFF в 32-разрядной системе. Преимущество этого очевидно, если вы рассматриваете коммерческие программы, такие как PixInsight. PixInsight может обрабатывать файлы TIFF меньше, чем 2147483648 байт при работе в 32-битных системах. Для обработки полноразмерных TIFF-файлов пользователь должен использовать 64-разрядную версию PixInsight на 64-разрядном компьютере. Вероятно, это потому, что программисты PixInsight использовали 64-битный тип для обработки смещений внутри. Поскольку мое решение использует только 32-битные типы, я могу обрабатывать полноразмерные файлы TIFF в 32-разрядной системе (если основная операционная система может обрабатывать большие файлы).