2010-07-27 18 views
24

¿Cuál es la diferencia entre fgetpos/fsetpos y ftell/fseek? ¿Para qué son buenos fgetpos y fsetpos?fgetpos/fsetpos y ftell/fseek

+0

Ver http://stackoverflow.com/questions/12119132/ftello-fseeko-vs-fgetpos-fsetpos Su respuesta es mucho mejor que la respuesta aceptada aquí. – Mecki

Respuesta

17

Bueno, desde la página de manual podemos ver que ftell y fseek usan tipo long int para representar desplazamientos (posiciones) en un archivo, y por lo tanto pueden estar limitados a desplazamientos que pueden representarse en un int largo. (Tipo largo int no se garantiza que contenga valores mayores que 2 ** 31-1, lo que limita el desplazamiento máximo a 2 gigabytes). Las nuevas funciones fgetpos y fsetpos, por otro lado, usan un typedef especial, fpos_t, para representar los offsets. El tipo detrás de este typedef, si se elige adecuadamente, puede representar desplazamientos arbitrariamente grandes, por lo que fgetpos y fsetpos se pueden usar con archivos arbitrariamente grandes. fgetpos y fsetpos también registran el estado asociado a las transmisiones multibyte.

+5

** ¡Esta respuesta es incorrecta! ** Si solo quieres buscar más allá de '2 ** 31-1', entonces está' fseeko'. La respuesta correcta es que 'fgetpos' solo puede buscar una posición previamente obtenida por' fgetpos' y que 'fpos_t' ** no debe ** ser interpretada como un entero, como dice la página man: * En algunos no- Sistemas UNIX, ** un objeto fpos_t puede ser un objeto complejo ** y estas rutinas pueden ser la única forma de reposicionar de forma portátil una secuencia de texto. * – Mecki

+0

@Mecki Sí, de hecho, esta respuesta es incorrecta. Por lo que yo entiendo, mi respuesta a continuación es la única correcta. – HughHughTeotl

+1

No, la respuesta no es incorrecta, pero es insuficiente. Establece correctamente los límites de 'fseek' y sus amigos, y dice correctamente que' fgetpos' y sus amigos son una opción que no tiene tales límites. La respuesta anterior nunca dice que se puede mezclar 'fseek' y' fsetpos' y firends, lo que de hecho es peligroso. Además, nunca establece que 'fpos_t' es un tipo integral. En su lugar, Mecki sugiere 'fseeko' y firends que no son funciones estándar de ISO-C (sino funciones POSIX). – math

-2

No hay diferencia en el aspecto funcional, aunque las interfaces se definen de manera diferente. Ambos se implementan porque ambos son parte de POSIX.

+2

Ambas interfaces son de ISO C, no de POSIX. Y existen profundas diferencias funcionales cuando los archivos son muy grandes. – zwol

+0

Su diferencia es la forma en que pueden abordar la posición: ya sea por 'long int' o por' fpos_t'. – math

17

Ninguna de las respuestas anteriores son correctas - de hecho, si se utiliza de manera intercambiable con fsetposfseek se podría introducir un fallo de seguridad (https://www.securecoding.cert.org/confluence/pages/viewpage.action?pageId=20087255).

La razón es que el argumento fpos_t *pos en fsetpos no es en realidad un número entero, por lo que no se puede usar para buscar ubicaciones arbitrarias en un archivo. Los únicos valores válidos son, por lo tanto, los obtenidos a partir del fgetpos. Como dicen los documentos,

El indicador de posición de archivos interno asociado con la corriente se establece en la posición representada por pos, que es un puntero a un objeto fpos_tcuyo valor haya sido obtenido previamente por una llamada a fgetpos.

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

Si lo que quieres es la capacidad de buscar en lugares arbitrarios allá límite de 32 bits, a continuación, utilizar ftello/fseeko y compilar con #define _FILE_OFFSET_BITS 64.

+0

No es la respuesta exacta para la pregunta, ¡pero muy buena como propina! ¡Gracias! – likern

+1

@likern Esta es exactamente la respuesta a la pregunta. Y también es la respuesta correcta, la respuesta aceptada es absolutamente incorrecta, ya que 'fpos_t' puede no ser un número entero (el estándar no requiere que sea). – Mecki

+0

'ftello' y' fseeko' son funciones POSIX. Además, el estándar C11 establece en 7.21.9.1:"La función fgetpos almacena los valores actuales del estado de análisis (si corresponde) y el indicador de posición de archivo para el flujo señalado por flujo en el objeto al que apunta pos " Además: en 7.21.1 se establece: "' fpos_t' que es un tipo de objeto completo distinto de un tipo de matriz capaz de registrar toda la información necesaria para especificar únicamente cada posición dentro de un archivo " Sin embargo, al menos en mi sistema' fpos_t' es un '__darwin_off_t' que resulta ser un' __int64_t'. Use fsetpos y fgetpos cuando sea posible – math

3

fgetpos() va con fsetpos(). Y ftell() va con fseek().

fgetpos() se ve prácticamente como ftell() porque ambos toman un parámetro FILE *, y ambos devuelven algún tipo de posición en el archivo, aunque con un estilo ligeramente diferente. Pero consiga esto: SOLAMENTE fseek() le permite buscar desde el principio del archivo, desde su posición actual en el archivo, y hacia atrás desde el final del archivo (el tercer argumento para fseek() es SEEK_SET, SEEK_CUR, y SEEK_END) fsetpos() no hace esto. fsetpos() se limita a volver a la posición que obtuviste de fgetpos().

Digamos que quiere leer un archivo en la memoria. ¿Cuánto montón necesitas de malloc()? Necesitas el tamaño del archivo. Y aún no he encontrado ninguna función en la biblioteca estándar C que le diga el tamaño de un archivo, aunque algunos compiladores C pueden agregar una función no estándar. Por ejemplo, Borland Turbo C tenía filelength(). Pero no he visto filelength() entre la biblioteca STANDARD C.

Entonces, lo que puede hacer es usar fseek() a 0 bytes antes del FIN del archivo. Luego use ftell() para obtener la posición en bytes, y base su cálculo para la cantidad de memoria del montón en eso.

¿Qué otra cosa podría hacer para obtener el tamaño del archivo?Puedes usar fgetc() para leer cada personaje, contando hasta llegar al final. Pero creo que usar fseek() y ftell() es mejor y más fácil.