Поиск и чтение больших файлов в приложении Linux C ++ - PullRequest
14 голосов
/ 24 июня 2009

Я сталкиваюсь с целочисленным переполнением, используя стандартные опции ftell и fseek внутри G ++, но, думаю, я ошибся, поскольку кажется, что ftell64 и fseek64 недоступны. Я искал, и многие веб-сайты ссылаются на lseek с типом данных off64_t , но я не нашел примеров, ссылающихся на нечто, равное fseek . Прямо сейчас файлы, в которых я читаю, - это файлы размером 16 ГБ + CSV, ожидаемые как минимум вдвое больше.

Без каких-либо внешних библиотек, какой самый простой метод для достижения структуры, подобной паре fseek / ftell ? Мое приложение сейчас работает с использованием стандартных библиотек GCC / G ++ для 4.x.

Ответы [ 5 ]

27 голосов
/ 24 июня 2009

fseek64 - это функция C. Чтобы сделать его доступным, вам нужно определить _FILE_OFFSET_BITS = 64, прежде чем включать системные заголовки, которые более или менее определят fseek как фактически fseek64. Или сделайте это в аргументах компилятора, например gcc -D_FILE_OFFSET_BITS = 64 ....

http://www.suse.de/~aj/linux_lfs.html имеет большую поддержку больших файлов в Linux:

  • Скомпилируйте ваши программы с помощью "gcc -D_FILE_OFFSET_BITS = 64". Это заставляет все вызовы доступа к файлу использовать 64-битные варианты. Меняются также несколько типов, например off_t становится off64_t. Поэтому важно всегда использовать правильные типы и не использовать, например, int вместо off_t. Для переносимости с другими платформами вы должны использовать getconf LFS_CFLAGS, который будет возвращать -D_FILE_OFFSET_BITS = 64 на платформах Linux, но может возвращать что-то другое, например, на. Solaris. Для связи вы должны использовать флаги связи, о которых сообщается через getconf LFS_LDFLAGS. В системах Linux вам не нужны специальные флаги ссылок.
  • Определите _LARGEFILE_SOURCE и _LARGEFILE64_SOURCE. С этими определениями вы можете напрямую использовать функции LFS, такие как open64.
  • Используйте флаг O_LARGEFILE с открытым для работы с большими файлами.
10 голосов
/ 24 июня 2009

Если вы хотите придерживаться стандартных интерфейсов ISO C, используйте fgetpos() и fsetpos(). Однако эти функции полезны только для сохранения файловой позиции и возврата к той же позиции позже. Они представляют позицию, используя тип fpos_t, который не обязательно должен быть целочисленным типом данных. Например, в системе на основе записей это может быть структура, содержащая номер записи и смещение в записи. Это может быть слишком ограничивающим.

POSIX определяет функции ftello() и fseeko(), которые представляют позицию с использованием типа off_t. Это должен быть целочисленный тип, а значение - это смещение в байтах от начала файла. Вы можете выполнить арифметику и использовать fseeko() для выполнения относительного поиска. Это будет работать в Linux и других системах POSIX.

Кроме того, скомпилируйте с -D_FILE_OFFSET_BITS=64 (Linux / Solaris). Это определит off_t как 64-битный тип (то есть off64_t) вместо long и переопределит функции, которые используют смещения файлов, чтобы быть версиями, которые принимают 64-битные смещения. Это значение по умолчанию при компиляции для 64-битной системы, поэтому в этом случае нет необходимости.

5 голосов
/ 24 июня 2009

Вы пробовали fseeko () с _FILE_OFFSET_BITS символом препроцессора, установленным на 64 ?

Это даст вам fseek () -подобный интерфейс, но с параметром смещения типа off_t вместо long . Установка _FILE_OFFSET_BITS = 64 сделает off_t 64-битным типом.

То же самое относится и к ftello () .

5 голосов
/ 24 июня 2009

fseek64() не является стандартным, документы компилятора должны указать, где его найти.

Вы пробовали fgetpos и fsetpos? Они предназначены для больших файлов, и реализация обычно использует 64-битный тип в качестве основы для fpos_t.

2 голосов
/ 24 июня 2009

Используйте fsetpos(3) и fgetpos(3). Они используют тип данных fpos_t, который, как я считаю, гарантированно может содержать не менее 64 бит.

...