в чем разница между fgetpos / fsetpos и ftell / fseek - PullRequest
27 голосов
/ 28 июля 2010

В чем разница между использованием функций fgetpos() и fsetpos() и использованием функций ftell() и fseek() для получения и установки позиции в файле?

Для чего нужны fgetpos() и fsetpos()? Почему бы их использовать вместо ftell() и fseek()?

Ответы [ 4 ]

21 голосов
/ 10 января 2014

Ни один из приведенных выше ответов не является правильным - фактически, если вы используете fsetpos взаимозаменяемо с fseek, вы могли бы ввести уязвимость безопасности (https://www.securecoding.cert.org/confluence/pages/viewpage.action?pageId=20087255).

Причина в том, что аргумент fpos_t *pos для fsetpos на самом деле не является целым числом, поэтому его нельзя использовать для поиска произвольных мест в файле. Поэтому единственными действительными значениями являются значения, полученные из fgetpos. Как говорят документы,

Внутренний указатель позиции файла, связанный с потоком, устанавливается на позицию, представленную pos, которая является указателем на fpos_t объект , значение которого должно быть предварительно получено при вызове fgetpos.

(http://www.cplusplus.com/reference/cstdio/fsetpos/)

Если все, что вам нужно, это возможность искать произвольные местоположения за пределами 32-битной границы, тогда используйте ftello / fseeko и скомпилируйте с #define _FILE_OFFSET_BITS 64.

17 голосов
/ 28 июля 2010

Итак, из man-страницы видно, что ftell и fseek используют тип long int для представления смещений (позиций) в файле и поэтому могут быть ограничены смещениями, которые могут быть представлены в long int.(Тип long int не гарантирует хранения значений больше 2 ** 31-1, ограничивая максимальное смещение до 2 гигабайт).Более новые функции fgetpos и fsetpos, с другой стороны, используют специальный typedef, fpos_t, для представления смещений.Тип, стоящий за этим typedef, при правильном выборе может представлять произвольно большие смещения, поэтому fgetpos и fsetpos могут использоваться с произвольно большими файлами.fgetpos и fsetpos также записывают состояние, связанное с многобайтовыми потоками.

3 голосов
/ 13 июня 2014

fgetpos () идет вместе с fsetpos (). И ftell () идет вместе с fseek ().

fgetpos () выглядит практически как ftell (), потому что оба принимают параметр FILE *, и оба возвращают какую-то позицию в файле, хотя и с немного другим стилем. Но получите следующее: ТОЛЬКО fseek () позволяет искать с начала файла, с текущей позиции в файле и обратно с конца файла (третий аргумент для fseek () - SEEK_SET, SEEK_CUR и SEEK_END. ). fsetpos () не делает этого. Функция fsetpos () ограничена возвратом к той позиции, которую вы получили из fgetpos ().

Допустим, вы хотите прочитать файл в память. Сколько кучи вам нужно от malloc ()? Вам нужен размер файла. И мне еще предстоит найти какую-либо функцию в стандартной библиотеке C, которая сообщит вам размер файла, хотя некоторые компиляторы C могут добавить нестандартную функцию. Например, Borland Turbo C имеет длину файла (). Но я не видел filelength () среди стандартной библиотеки C.

Итак, вы можете использовать fseek () для 0 байтов перед END файла. Затем используйте ftell (), чтобы получить позицию в байтах, и основывайте свои вычисления для объема памяти кучи на этом.

Что еще можно сделать, чтобы получить размер файла? Вы можете использовать fgetc () для чтения каждого символа, считая до конца. Но я думаю, что использовать fseek () и ftell () лучше и проще.

0 голосов
/ 28 июля 2010

Функциональной разницы нет, хотя интерфейсы определены по-разному. Они оба реализованы, потому что оба являются частью POSIX.

...