Was ist der Unterschied zwischen fgetpos/fsetpos und ftell/fseek

Lesezeit: 5 Minuten

Benutzeravatar von carlfilips
karlfilips

Was ist der Unterschied zwischen der Verwendung der Funktionen fgetpos() und fsetpos() und Nutzung der Funktionen ftell() und fseek() um eine Position in einer Datei zu bekommen und zu setzen?

Was sind fgetpos() und fsetpos() gut für? Warum sollten sie stattdessen verwendet werden ftell() und fseek()?

  • Siehe stackoverflow.com/questions/12119132/… ​​Die Antwort ist viel besser als die akzeptierte Antwort hier.

    – Mecki

    24. Juni 2015 um 23:39 Uhr

Keine der obigen Antworten ist richtig – in der Tat, wenn Sie verwenden fsetpos austauschbar mit fseek Sie könnten eine Sicherheitslücke einführen (https://www.securecoding.cert.org/confluence/pages/viewpage.action?pageId=20087255).

Der Grund ist, dass die fpos_t *pos Argument zu fsetpos ist eigentlich keine ganze Zahl, daher kann es nicht verwendet werden, um nach beliebigen Orten in einer Datei zu suchen. Die einzigen gültigen Werte sind daher diejenigen, die aus erhalten werden fgetpos. Wie die Dokumente sagen,

Der dem Stream zugeordnete interne Dateipositionsindikator wird auf die durch dargestellte Position gesetzt poswas ein Zeiger auf eine ist fpos_t Objekt deren Wert zuvor durch einen Aufruf von erhalten wurde fgetpos.

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

Wenn Sie nur nach beliebigen Orten jenseits der 32-Bit-Grenze suchen möchten, verwenden Sie ftello / fseeko und mit kompilieren #define _FILE_OFFSET_BITS 64.

  • Eigentlich keine exakte Antwort auf die Frage, aber als Tipp sehr gut! Vielen Dank!

    – Likern

    17. Februar 2014 um 2:36 Uhr

  • @liker Das ist genau die Antwort auf die Frage. Und es ist auch die richtige Antwort, die akzeptierte Antwort ist absolut falsch, da fpos_t darf überhaupt keine Ganzzahl sein (der Standard verlangt dies nicht).

    – Mecki

    24. Juni 2015 um 23:36 Uhr

  • ftello und fseeko sind POSIX-Funktionen. Darüber hinaus heißt es im C11-Standard in 7.21.9.1: „Die fgetpos-Funktion speichert die aktuellen Werte des Parsing-Status (falls vorhanden) und des Dateipositionsindikators für den Stream, auf den stream zeigt, in dem Objekt, auf das pos zeigt.“ Außerdem: in 7.21. 1 heißt es:“fpos_t Dies ist ein vollständiger Objekttyp, der kein Array-Typ ist, der in der Lage ist, alle Informationen aufzuzeichnen, die erforderlich sind, um jede Position innerhalb einer Datei eindeutig anzugeben fpos_t ist ein __darwin_off_t was sich als a herausstellt __int64_t. Verwenden Sie nach Möglichkeit fsetpos und fgetpos

    – Mathematik

    3. Mai 2016 um 8:37 Uhr


  • Ich kann den Link nicht öffnen :/ Gibt es eine Kopie der Begründung?

    – Flammenfeuer

    2. Dezember 2019 um 14:28 Uhr

  • Ich werde nicht sagen, dass das falsch ist, weil ich es nicht weiß, aber jedes Mal, wenn ich von Confluence Ratschläge zu potenziellen C-Sicherheitsrisiken erhalten habe, haben sie sich geirrt.

    – Jäger Köhler

    10. August 2021 um 16:24 Uhr

Nun, der Manpage können wir entnehmen, dass ftell und fseek den Typ long int verwenden, um Offsets (Positionen) in einer Datei darzustellen, und daher möglicherweise auf Offsets beschränkt sind, die in einem long int dargestellt werden können. (Es ist nicht garantiert, dass der Typ long int Werte größer als 2**31-1 enthält, was den maximalen Offset auf 2 Gigabyte begrenzt). Die neueren Funktionen fgetpos und fsetpos verwenden dagegen eine spezielle Typedef, fpos_t, um die Offsets darzustellen. Der Typ hinter dieser Typedef kann bei entsprechender Wahl beliebig große Offsets darstellen, sodass 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.

  • Diese Antwort ist falsch! Wenn Sie einfach nur darüber hinaus suchen möchten 2**31-1 dann gibt es fseeko. Die richtige Antwort ist die fgetpos kann nur eine Position anstreben, die zuvor von erreicht wurde fgetpos und das fpos_t darf nicht überhaupt als Integer interpretiert werden, wie die Manpage sagt: Auf einigen Nicht-UNIX-Systemen ein fpos_t-Objekt kann ein komplexes Objekt sein und diese Routinen können die einzige Möglichkeit sein, einen Textstrom portabel neu zu positionieren.

    – Mecki

    24. Juni 2015 um 23:33 Uhr


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

    – HughHughTeotl

    26. Juni 2015 um 7:24 Uhr

  • Nein, die Antwort ist nicht falsch, aber unzureichend. Es gibt korrekt die Grenzen von an fseek und Freunde, und das sagt es richtig fgetpos und Freunde sind eine Option, die solche Grenzen nicht hat. Die obige Antwort besagt nie, dass Sie mischen können fseek und fsetpos und Freunde, was in der Tat gefährlich ist. Außerdem sagt es das nie fpos_t ist ein ganzzahliger Typ. Stattdessen schlägt Mecki vor fseeko und firends, die keine ISO-C-Standardfunktionen sind (aber POSIX-Funktionen).

    – Mathematik

    3. Mai 2016 um 8:46 Uhr

fgetpos() passt zu fsetpos(). Und ftell() passt zu fseek().

fgetpos() sieht praktisch wie ftell() aus, da beide einen FILE*-Parameter annehmen und beide eine Art Position in der Datei zurückgeben, wenn auch mit einem etwas anderen Stil. Aber verstehen Sie Folgendes: NUR mit fseek() können Sie vom Anfang der Datei, von Ihrer aktuellen Position in der Datei und rückwärts vom Ende der Datei 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.

Angenommen, 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 mitteilt, obwohl einige C-Compiler möglicherweise eine nicht standardmäßige Funktion hinzufügen. Zum Beispiel hatte Borland Turbo C filelength(). Aber ich habe filelength() nicht in der STANDARD C-Bibliothek gesehen.

Sie können also fseek() auf 0 Bytes vor dem ENDE der Datei verwenden. Verwenden Sie dann ftell(), um die Position in Bytes zu erhalten, und stützen Sie Ihre Berechnung für die Größe des Heap-Speichers darauf.

Was könnten Sie sonst tun, um die Dateigröße zu erhalten? Sie könnten fgetc() verwenden, um jedes Zeichen zu lesen und bis zum Ende zu zählen. Aber ich denke, die Verwendung von fseek() und ftell() ist besser und einfacher.

Benutzeravatar von m1tk4
m1tk4

Funktional gibt es keinen Unterschied, obwohl die Schnittstellen unterschiedlich definiert sind. Beide sind implementiert, weil beide Teil von POSIX sind.

1396740cookie-checkWas ist der Unterschied zwischen fgetpos/fsetpos und ftell/fseek

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy