2010-07-27 12 views
24

Qual è la differenza tra fgetpos/fsetpos e ftell/fseek? A cosa servono fgetpos e fsetpos?fgetpos/fsetpos e ftell/fseek

+0

Vedere http://stackoverflow.com/questions/12119132/ftello-fseeko-vs-fgetpos-fsetpos La risposta è molto meglio della risposta accettata qui. – Mecki

risposta

17

Bene, dalla pagina di manuale possiamo vedere che ftell e fseek utilizzano il tipo long int per rappresentare gli offset (posizioni) in un file e possono quindi essere limitati a offset che possono essere rappresentati in un int lungo. (Digitare long int non è garantito per contenere valori superiori a 2 ** 31-1, limitando l'offset massimo a 2 gigabyte). Le nuove funzioni fgetpos e fsetpos, d'altra parte, usano uno speciale typedef, fpos_t, per rappresentare gli offset. Il tipo dietro questo typedef, se scelto appropriatamente, può rappresentare offset arbitrariamente grandi, quindi fgetpos e fsetpos possono essere usati con file arbitrariamente enormi. fgetpos e fsetpos registrano anche lo stato associato ai flussi multibyte.

+5

** Questa risposta non è corretta! ** Se vuoi solo cercare oltre "2 ** 31-1", allora c'è "fseeko". La risposta corretta è che 'fgetpos' può solo cercare una posizione precedentemente ottenuta da' fgetpos' e che 'fpos_t' ** non deve ** essere interpretato come un numero intero, come dice la pagina man: * Su alcuni non- Sistemi UNIX, ** un oggetto fpos_t può essere un oggetto complesso ** e queste routine possono essere l'unico modo per riposizionare in modo portatile un flusso di testo. * – Mecki

+0

@Mecki Sì, questa risposta è sbagliata. Per quanto ne so, la mia risposta è l'unica corretta. – HughHughTeotl

+1

Nessuna risposta è errata ma insufficiente. Stabilisce correttamente i limiti di 'fseek' e degli amici, e dice correttamente che' fgetpos' e gli amici sono un'opzione che non ha tali limiti. La risposta sopra non dice mai che puoi mischiare 'fseek' e' fsetpos' e firends, che è davvero pericoloso. Inoltre, non afferma mai che 'fpos_t' è un tipo integrale. Invece Mecki suggerisce 'fseeko' e gli amici che sono funzioni non-ISO-C-standard (ma funzioni POSIX). – math

-2

Non c'è alcuna differenza nel livello funzionale, sebbene le interfacce siano definite in modo diverso. Entrambi sono implementati perché entrambi fanno parte di POSIX.

+2

Entrambe queste interfacce provengono da ISO C, non POSIX. E ci sono profonde differenze funzionali quando i file diventano molto grandi. – zwol

+0

La differenza è il modo in cui possono indirizzare la posizione: sia per 'long int' che per' fpos_t'. – math

17

Nessuna delle risposte di cui sopra sono corrette - in realtà se si utilizza fsetpos in modo intercambiabile con fseek si potrebbe introdurre una falla di sicurezza (https://www.securecoding.cert.org/confluence/pages/viewpage.action?pageId=20087255).

Il motivo è che l'argomento fpos_t *pos su fsetpos non è in realtà un numero intero, quindi non può essere utilizzato per cercare posizioni arbitrarie in un file. Gli unici valori validi sono quindi quelli ottenuti da fgetpos. Come dicono i documenti,

L'indicatore di posizione file interno associato flusso è impostato nella posizione rappresentata dalla pos, che è un puntatore a un fpos_t oggetto cui valore deve essere precedentemente ottenuto mediante una chiamata a fgetpos.

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

Se invece si è interessati la possibilità di cercare di posizioni arbitrarie oltre a 32-bit di confine, quindi utilizzare ftello/fseeko e compilare con #define _FILE_OFFSET_BITS 64.

+0

Risposta non effettivamente esatta per la domanda, ma molto buona come suggerimento! Grazie! – likern

+1

@likern Questa è esattamente la risposta alla domanda. Ed è anche la risposta corretta, la risposta accettata è assolutamente errata, dato che 'fpos_t' potrebbe non essere affatto un numero intero (lo standard non lo richiede). – Mecki

+0

'ftello' e' fseeko' sono funzioni POSIX. Inoltre, lo standard C11 afferma in 7.21.9.1:" La funzione fgetpos memorizza i valori correnti dello stato di analisi (se presente) e l'indicatore di posizione del file per il flusso puntato da stream nell'oggetto puntato da pos " Inoltre: in 7.21.1 è dichiarato: "' fpos_t' che è un tipo di oggetto completo diverso da un tipo di matrice in grado di registrare tutte le informazioni necessarie per specificare in modo univoco ogni posizione all'interno di un file " Tuttavia, almeno sul mio sistema' fpos_t' è un '__darwin_off_t' che risulta essere un' __int64_t'. Utilizzare fsetpos e fgetpos quando possibile – math

3

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

fgetpos() sembra praticamente come ftell() perché entrambi hanno un parametro FILE * ed entrambi restituiscono un qualche tipo di posizione nel file, anche se con uno stile leggermente diverso. Ma ottieni questo: SOLO fseek() ti permette di cercare dall'inizio del file, dalla tua posizione corrente nel file, e al contrario dalla fine del file (il terzo argomento di fseek() è SEEK_SET, SEEK_CUR e SEEK_END). fsetpos() non lo fa. fsetpos() è limitato a tornare ad una posizione che hai da fgetpos().

Supponiamo di voler leggere un file in memoria. Di quanto heap hai bisogno da malloc()? Hai bisogno della dimensione del file. E non ho ancora trovato alcuna funzione nella libreria standard C che indichi la dimensione di un file, sebbene alcuni compilatori C possano aggiungere una funzione non standard. Ad esempio, Borland Turbo C aveva lunghezza del filetto(). Ma non ho visto il filelength() tra la libreria STANDARD C.

Quindi, ciò che si può fare è usare fseek() a 0 byte prima della FINE del file. Quindi utilizzare ftell() per ottenere la posizione in byte e basare il calcolo per la quantità di memoria heap su quello.

Cos'altro si può fare per ottenere le dimensioni del file?Puoi usare fgetc() per leggere ogni carattere, contando fino alla fine. Ma penso che usare fseek() e ftell() sia migliore e più facile.