2008-09-28 2 views
8

Sehr einfach ausgedrückt, ich habe den folgenden Code-Schnipsel:Ende Zeiger FILE * ist auf eine Größe von geschriebenen Daten nicht gleich

FILE* test = fopen("C:\\core.u", "w"); 
printf("Filepointer at: %d\n", ftell(test)); 
fwrite(data, size, 1, test); 
printf("Written: %d bytes.\n", size); 
fseek(test, 0, SEEK_END); 
printf("Filepointer is now at %d.\n", ftell(test)); 
fclose(test); 

und es gibt:

Filepointer at: 0 
Written: 73105 bytes. 
Filepointer is now at 74160. 

Warum das so ist? Warum stimmt die Anzahl der geschriebenen Bytes nicht mit dem Dateizeiger überein?

+2

Ich empfehle, keine NT-Stil Pfade in fopen() - Argumente zu verwenden. Windows unterstützt auch POSIX-Pfade, die portabel sind und kein Entweichen von '\' erfordern. – Terminus

Antwort

19

Da Sie die Datei im Textmodus öffnen, werden Endzeilenmarkierungen wie LF in CR/LF konvertiert.

Dies ist wahrscheinlich, wenn Sie unter Windows laufen (und Sie wahrscheinlich sind, vorausgesetzt, dass Ihr Dateiname mit "c:\" beginnt).

Wenn Sie die Datei in "wb" Modus zu öffnen, ich vermute, Sie sind die Zahlen identisch finden:

Das Argument Modus:

FILE* test = fopen("C:\\core.u", "wb"); 

Der C99-Standard dies in 7.19.5.3 The fopen function zu sagen hat zeigt auf eine Zeichenfolge. Wenn die Zeichenfolge eine der folgenden ist, wird die Datei im angegebenen Modus geöffnet. Andernfalls ist das Verhalten nicht definiert.

r öffnen Textdatei zum Lesen
w truncate auf die Länge Null oder Textdatei erstellen
a append zum Schreiben; offen oder zum Lesen
wb Trunkat auf der Länge Null, oder erstellen Binärdatei für das Schreiben
ab append-Textdatei für das Schreiben an end of file
rb offene Binärdatei erstellen; offene oder Binärdatei erstellen zum Schreiben an end of file
r+ offenen Textdatei für update (Lesen und Schreiben)
w+ Trunkat auf die Länge Null oder eine Textdatei erstellen for update
a+ append; offen oder Textdatei für Update, das Schreiben an End-of-Datei
r+b oder rb+ offene Binärdatei für update (Lesen und Schreiben)
w+b oder wb+ auf die Länge Null oder erstellen binäre Datei für die Aktualisierung gestutzt
a+b oder ab+ erstellen anhängen; öffnen oder erstellen binäre Datei für die Aktualisierung, das Schreiben an End-of-Datei

können Sie sehen, dass sie zwischen w und wb unterscheiden. Ich glaube nicht, dass eine Implementierung erforderlich ist, um die zwei unterschiedlich zu behandeln, aber es ist normalerweise sicherer Binärmodus für binäre Daten zu verwenden.

+1

Dies ist eine ziemlich dunkle Ecke der Sprache, fürchte ich. Man neigt dazu, nicht zu wissen, dass es da ist, bis sie von ihm gebissen werden. Schöner Fang! – fbrereto

+0

Es ist erwähnenswert, dass POSIX die Implementierung erfordert, um sie nicht anders zu behandeln. –

0

was gibt fwrite zurück? normalerweise sollte der Rückgabewert die Anzahl der geschriebenen Bytes sein. Auch, was antwortet die ftell() mit rechts vor dem fseek?

Es könnte helfen, zu wissen, welches Betriebssystem, C-Compiler-Version und C-Bibliothek.

0

Ein Dateizeiger ist ein Cookie. Es hat keinen Wert. Das einzige, wofür Sie es verwenden können, ist den gleichen Ort in einer Datei zu suchen. Ich bin mir nicht einmal sicher, ob ISO C garantiert, dass ftell steigende Werte zurückgibt. Wenn Sie das nicht glauben, sehen Sie sich bitte die verschiedenen seek() -Modi an. Sie existieren genau, weil die Position kein einfacher Byte-Offset ist.

+0

Ja, aber sie müssen * irgendwie * implementiert werden. Selbst wenn es nicht durch den Standard spezifiziert ist, werden Dateizeiger in vielen Implementierungen einfach Byte-Offsets sein, so dass es zu pedantisch ist zu sagen, dass es "keinen Wert" hat. – Tom

+0

Es ist kein Cookie. Es ist ein Byte-Offset im Binärmodus. Text-Modus ist die Hölle und macht fast keine Garantien über irgendetwas funktioniert, und sollte einfach nicht verwendet werden. –

+0

@R ..: Bitte geben Sie den Teil des C-Standards an, der dies garantiert. Auch der Byte-Modus ist eine POSIX-Erweiterung. – MSalters

0

Windows schreibt tatsächlich nicht alle Daten in die Datei ohne Flush und möglicherweise ein fsync. Vielleicht deshalb

Verwandte Themen