Was ist der Grund dafür, dass fread/fwrite Größe und Anzahl als Argumente nehmen?

Lesezeit: 6 Minuten

Benutzeravatar von David Holm
David Holm

Wir hatten hier auf der Arbeit eine Diskussion darüber, warum Angst () und fwrite() Nehmen Sie eine Größe pro Mitglied und zählen Sie und geben Sie die Anzahl der gelesenen/geschriebenen Mitglieder zurück, anstatt nur einen Puffer und eine Größe zu nehmen. Die einzige Verwendung dafür, die uns einfallen könnte, ist, wenn Sie ein Array von Strukturen lesen/schreiben möchten, die nicht gleichmäßig durch die Plattformausrichtung teilbar sind und daher aufgefüllt wurden, aber das kann nicht so häufig sein, dass diese Wahl gerechtfertigt ist im Design.

Aus Angst(3):

Die Funktion fread() liest nmemb Datenelemente, jede Byte lang, aus dem Stream, auf den stream zeigt, und speichert sie an der durch ptr angegebenen Stelle.

Die Funktion fwrite() schreibt nmemb Datenelemente, jede Größe Bytes lang, in den Stream, auf den stream zeigt, und erhält sie von der durch ptr angegebenen Stelle.

fread() und fwrite() geben die Anzahl der erfolgreich gelesenen oder geschriebenen Elemente zurück (dh nicht die Anzahl der Zeichen). Wenn ein Fehler auftritt oder das Dateiende erreicht ist, ist der Rückgabewert eine kurze Elementanzahl (oder Null).

  • hallo das ist eine gute frage. ich habe mich immer darüber gewundert

    – Johannes Schaub – litb

    17. November 2008 um 16:11 Uhr

  • Bitte sehen Sie sich diesen Thread an: stackoverflow.com/questions/8589425/how-does-fread-really-work

    – Franken

    14. April 2012 um 20:42 Uhr

Benutzeravatar von Peter Miehle
Peter Miele

Der Unterschied bei fread(buf, 1000, 1, stream) und fread(buf, 1, 1000, stream) ist, dass man im ersten Fall nur einen Chunk von 1000 Bytes oder gar nichts bekommt, wenn die Datei kleiner ist und im zweiten Fall alles in der Datei kleiner und bis 1000 Bytes bekommt.

  • Obwohl das stimmt, erzählt das nur einen kleinen Teil der Geschichte. Es wäre besser, etwas zu kontrastieren, das beispielsweise ein Array von int-Werten oder ein Array von Strukturen liest.

    – Jonathan Leffler

    17. November 2008 um 22:22 Uhr

  • Dies wäre eine großartige Antwort, wenn die Begründung abgeschlossen wäre.

    – Matt Tischler

    19. September 2010 um 4:32 Uhr

Benutzeravatar von Powerlord
Machtherr

Es basiert auf dem Wie Angst ist implementiert.

Die Single UNIX Specification sagt

Für jedes Objekt sollen Größenaufrufe an die Funktion fgetc() erfolgen und die Ergebnisse in der gelesenen Reihenfolge in einem Array aus unsigned char gespeichert werden, das genau das Objekt überlagert.

fgetc hat auch diesen Hinweis:

Da fgetc() mit Bytes arbeitet, kann das Lesen eines Zeichens, das aus mehreren Bytes besteht (oder “ein Multi-Byte-Zeichen”) mehrere Aufrufe von fgetc() erfordern.

Natürlich ist dies älter als ausgefallene Zeichencodierungen mit variablen Bytes wie UTF-8.

Der SUS merkt an, dass dies tatsächlich aus den ISO C-Dokumenten stammt.

Dies sind reine Spekulationen, aber damals (einige gibt es noch) waren viele Dateisysteme keine einfachen Byteströme auf einer Festplatte.

Viele Dateisysteme waren datensatzbasiert. Um solche Dateisysteme effizient zu erfüllen, müssen Sie die Anzahl der Elemente (“Datensätze”) angeben, damit fwrite/fread auf dem Speicher als Datensätze arbeiten kann, nicht nur als Byte-Streams.

  • Ich bin froh, dass jemand das angesprochen hat. Ich habe viel mit Dateisystemspezifikationen und FTP gearbeitet, und Datensätze/Seiten und andere Blockierungskonzepte werden sehr stark unterstützt, obwohl niemand diese Teile der Spezifikationen mehr verwendet.

    – Matt Tischler

    19. September 2010 um 4:58 Uhr

Benutzeravatar von Michael Burr
Michael Burr

Lassen Sie mich diese Funktionen hier reparieren:

size_t fread_buf( void* ptr, size_t size, FILE* stream)
{
    return fread( ptr, 1, size, stream);
}


size_t fwrite_buf( void const* ptr, size_t size, FILE* stream)
{
    return fwrite( ptr, 1, size, stream);
}

Was eine Begründung für die Parameter angeht fread()/fwrite(), ich habe mein Exemplar von K&R vor langer Zeit verloren, also kann ich nur raten. Ich denke, eine wahrscheinliche Antwort ist, dass Kernighan und Ritchie einfach gedacht haben, dass die Ausführung binärer I/O am natürlichsten auf Arrays von Objekten erfolgen würde. Außerdem haben sie vielleicht gedacht, dass Block-I/O auf einigen Architekturen schneller/einfacher zu implementieren wäre oder was auch immer.

Obwohl die C-Norm das vorschreibt fread() und fwrite() umgesetzt werden im Sinne von fgetc() und fputc(), denken Sie daran, dass der Standard lange nach der Definition von C durch K&R entstand und dass die im Standard spezifizierten Dinge möglicherweise nicht in den ursprünglichen Ideen des Designers enthalten waren. Es ist sogar möglich, dass Dinge, die in K&Rs „The C Programming Language“ gesagt werden, nicht dieselben sind wie zu der Zeit, als die Sprache zum ersten Mal entworfen wurde.

Abschließend ist hier, was PJ Plauger zu sagen hat fread() in “Die Standard-C-Bibliothek”:

Wenn die size (zweites) Argument größer als eins ist, können Sie nicht feststellen, ob die Funktion auch bis zu gelesen hat size - 1 zusätzliche Zeichen über das hinaus, was es berichtet. In der Regel rufen Sie die Funktion besser als auf fread(buf, 1, size * n, stream); Anstatt von
fread(buf, size, n, stream);

Im Grunde sagt er das fread()Die Schnittstelle von ist defekt. Zum fwrite() er merkt an, dass “Schreibfehler im Allgemeinen selten sind, also ist dies kein großer Mangel” – eine Aussage, der ich nicht zustimmen würde.

Benutzeravatar von dolch
dolch

Wahrscheinlich geht es auf die Art und Weise zurück, wie die Datei-E/A implementiert wurde. (früher) Es könnte schneller gewesen sein, Dateien in Blöcken zu schreiben / zu lesen, als alles auf einmal zu schreiben.

Benutzeravatar von Supercat
Superkatze

Separate Argumente für Größe und Anzahl zu haben, könnte bei einer Implementierung vorteilhaft sein, die das Lesen von Teildatensätzen vermeiden kann. Wenn man Single-Byte-Lesevorgänge von so etwas wie einer Pipe verwenden würde, müsste man, selbst wenn man Daten mit festem Format verwendet, die Möglichkeit berücksichtigen, dass ein Datensatz auf zwei Lesevorgänge aufgeteilt wird. Wenn stattdessen z. B. ein nicht blockierender Lesevorgang von bis zu 40 Datensätzen mit jeweils 10 Bytes angefordert werden könnte, wenn 293 Bytes verfügbar sind, und das System 290 Bytes (29 ganze Datensätze) zurückgeben könnte, während 3 Bytes für den nächsten Lesevorgang bereit bleiben, würde dies der Fall sein viel bequemer sein.

Ich weiß nicht, inwieweit Implementierungen von fread mit einer solchen Semantik umgehen können, aber sie könnten sicherlich nützlich sein für Implementierungen, die versprechen, sie zu unterstützen.

Vanuans Benutzeravatar
Vanuan

Ich denke, es liegt daran, dass C die Funktionsüberladung fehlt. Wenn es welche gäbe, wäre Größe überflüssig. Aber in C können Sie die Größe eines Array-Elements nicht bestimmen, Sie müssen eine angeben.

Bedenken Sie:

int intArray[10];
fwrite(intArray, sizeof(int), 10, fd);

Wenn fwrite eine Anzahl von Bytes akzeptiert, könnten Sie Folgendes schreiben:

int intArray[10];
fwrite(intArray, sizeof(int)*10, fd);

Aber es ist einfach ineffizient. Sie haben sizeof(int) mal mehr Systemaufrufe.

Ein weiterer Punkt, der berücksichtigt werden sollte, ist, dass Sie normalerweise nicht möchten, dass ein Teil eines Array-Elements in eine Datei geschrieben wird. Sie wollen die ganze ganze Zahl oder nichts. fwrite gibt eine Reihe erfolgreich geschriebener Elemente zurück. Wenn Sie also feststellen, dass nur 2 Low-Bytes eines Elements geschrieben werden, was würden Sie tun?

Auf einigen Systemen (aufgrund der Ausrichtung) können Sie nicht auf ein Byte einer Ganzzahl zugreifen, ohne eine Kopie zu erstellen und zu verschieben.

1421740cookie-checkWas ist der Grund dafür, dass fread/fwrite Größe und Anzahl als Argumente nehmen?

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

Privacy policy