2010-07-27 6 views
24

Was ist der Unterschied zwischen fgetpos/fsetpos und ftell/fseek? Wofür sind Fgetpos und Fsetpos gut?fgetpos/fsetpos und ftell/fseek

+0

Siehe http://stackoverflow.com/questions/12119132/ftello-fseeko-vs-fgetpos-fsetpos Die Antwort ist viel besser als die angenommene Antwort hier. – Mecki

Antwort

17

Nun, von der Manpage können wir sehen, dass ftell und fseek long int verwenden, um Offsets (Positionen) in einer Datei darzustellen, und daher auf Offsets beschränkt sein können, die in einem langen int dargestellt werden können. (Der Typ long int garantiert nicht, dass Werte größer als 2 ** 31-1 enthalten sind, wodurch der maximale Offset auf 2 Gigabyte begrenzt wird). Die neueren Funktionen fgetpos und fsetpos verwenden andererseits einen speziellen Typdef, fpos_t, um die Offsets darzustellen. Der Typ hinter diesem Typdef kann, wenn er richtig gewählt wird, beliebig große Offsets darstellen, so dass fgetpos und fsetpos mit beliebig großen Dateien verwendet werden können. fgetpos und fsetpos zeichnen auch den Zustand auf, der Multibyte-Streams zugeordnet ist.

+5

** Diese Antwort ist falsch! ** Wenn Sie nur nach '2 ** 31-1' suchen wollen, dann gibt es 'fseeko'. Die richtige Antwort ist, dass 'fgetpos' nur nach einer Position suchen kann, die zuvor von' fgetpos' erhalten wurde und dass 'fpos_t' ** nicht ** als ganze Zahl interpretiert werden muss, wie die man-Seite sagt: * UNIX-Systeme, ** ein fpos_t-Objekt kann ein komplexes Objekt sein ** und diese Routinen können die einzige Möglichkeit sein, einen Text-Stream portabel neu zu positionieren. * – Mecki

+0

@Mecki Ja, diese Antwort ist falsch. Soweit ich verstehe, ist meine Antwort unten die einzig richtige. – HughHughTeotl

+1

Nein, die Antwort ist nicht inkorrekt, aber nicht ausreichend. Es gibt korrekt die Grenzen von "fseek" und Freunden an und es sagt richtig, dass 'fgetpos' und Freunde eine Option sind, die solche Grenzen nicht hat. Die obige Antwort besagt niemals, dass man 'fseek' und' fsetpos' und Firends mischen kann, was in der Tat gefährlich ist. Außerdem gibt es niemals an, dass 'fpos_t' ein ganzzahliger Typ ist. Stattdessen schlägt Mecki 'fseeko' und firmends vor, die keine ISO-C-Standardfunktionen sind (aber POSIX-Funktionen). – math

-2

Es gibt keinen Unterschied in der Funktionalität, obwohl die Schnittstellen unterschiedlich definiert sind. Beide werden implementiert, da beide Teil von POSIX sind.

+2

Beide Schnittstellen stammen von ISO C, nicht von POSIX. Und es gibt tiefgreifende funktionale Unterschiede, wenn die Dateien sehr groß werden. – zwol

+0

Ihr Unterschied ist die Art, wie sie die Position ansprechen können: entweder durch 'long int' oder durch' fpos_t'. – math

17

Keine der oben genannten Antworten sind richtig - in der Tat, wenn Sie verwenden fsetpos austauschbar mit fseek Sie eine Sicherheitslücke vorstellen könnte (https://www.securecoding.cert.org/confluence/pages/viewpage.action?pageId=20087255).

Der Grund ist, dass das fpos_t *pos Argument zu fsetpos nicht wirklich eine ganze Zahl ist, so dass es nicht verwendet werden kann, um beliebige Positionen in einer Datei zu suchen. Die einzigen gültigen Werte sind daher solche, die von fgetpos erhalten werden. Da die docs sagen

Die interne Indikatordateiposition mit dem Strom zugeordnet ist, zu dem durch pos, dargestellten Position eingestellt, die ein Zeiger auf ein fpos_t Objekt , deren Wert zuvor durch einen Aufruf von fgetpos erhalten wird.

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

Wenn alles, was Sie die Möglichkeit, beliebigen Orten über 32-Bit-Grenze suchen möchten, dann ftello/fseeko verwenden und kompilieren mit #define _FILE_OFFSET_BITS 64.

+0

Nicht wirklich genaue Antwort auf die Frage, aber sehr gut als Tipp! Vielen Dank! – likern

+1

@likern Dies ist genau die Antwort auf die Frage. Und es ist auch die richtige Antwort, die angenommene Antwort ist absolut falsch, da 'fpos_t' möglicherweise gar keine Ganzzahl ist (der Standard verlangt es nicht). – Mecki

+0

'ftello' und' fseeko' sind POSIX-Funktionen. Darüber hinaus gibt der C11-Standard in 7.2.1.9.1:"die Funktion fgetpos die aktuellen Werte des Parse-Zustands (falls vorhanden) und den Dateipositionsindikator für den Stream wieder, auf den der Stream in dem Objekt zeigt, auf das durch pos " Außerdem: in 7.21.1 es heißt: "' fpos_t' ist ein vollständiger Objekttyp, der nicht ein Array-Typ ist, der alle Informationen erfassen kann, die benötigt werden, um jede Position innerhalb einer Datei eindeutig zu spezifizieren " Jedenfalls zumindest auf meinem System' fpos_t' ist ein '__darwin_off_t', das sich als' __int64_t' herausstellt. Verwenden Sie fsetpos und fgetpos wenn möglich – math

3

fgetpos() geht mit fsetpos(). Und ftell() geht mit fseek().

fgetpos() sieht praktisch wie ftell() aus, da beide einen FILE * -Parameter haben und beide eine Art Position in der Datei zurückgeben, allerdings mit einem etwas anderen Stil. Aber nimm folgendes: NUR fseek() erlaubt dir, vom Anfang der Datei an deiner aktuellen Position in der Datei und rückwärts vom Ende der Datei zu suchen (das dritte Argument für fseek() ist SEEK_SET, SEEK_CUR und SEEK_END)). fsetpos() tut dies nicht. fsetpos() ist darauf beschränkt, zu einer Position zurückzukehren, die Sie von fgetpos() erhalten haben.

Nehmen wir an, Sie möchten eine Datei in den Speicher lesen. Wie viel Heap benötigen Sie von malloc()? Sie benötigen die Größe der Datei. Und ich habe noch keine Funktion in der C-Standardbibliothek gefunden, die Ihnen die Größe einer Datei sagt, obwohl einige C-Compiler eine nicht-standardmäßige Funktion hinzufügen. Zum Beispiel hatte Borland Turbo C Dateilänge(). Aber ich habe Filength() nicht unter der STANDARD C-Bibliothek gesehen.

Also, was Sie tun können, ist fseek() zu 0 Bytes vor dem Ende der Datei. Verwenden Sie dann ftell(), um die Position in Byte zu ermitteln, und legen Sie die Berechnung für die Menge des Heapspeichers fest.

Was können Sie noch tun, um die Dateigröße zu erhalten?Sie können fgetc() verwenden, um jedes Zeichen zu lesen und zu zählen, bis Sie das Ende erreicht haben. Aber ich denke, mit fseek() und ftell() ist es besser und einfacher.

Verwandte Themen