105

ここでは、 fread()fwrite()がメンバーごとにサイズを取り、バッファーとサイズだけでなく、読み取り/書き込みされたメンバーの数をカウントして返す理由について話し合いました。私たちが思いつくことができる唯一の用途は、プラットフォームの配置によって均等に分割できないためにパディングされている構造の配列を読み取り/書き込みする場合ですが、これはこの選択を正当化するほど一般的ではありませんデザインで。

fread(3)から:

関数fread()は、ストリームが指すストリームから、各サイズがバイト長のデータのnmemb要素を読み取り、ptrで指定された場所に格納します。

関数fwrite()は、各サイズがバイト長のデータのnmemb要素を、streamが指すストリームに書き込み、ptrで指定された場所から取得します。

fread()およびfwrite()は、正常に読み取られた、または書き込まれた項目の数(つまり、文字数ではない)を返します。エラーが発生した場合、またはファイルの終わりに達した場合、戻り値は短いアイテム数(またはゼロ)です。

4

7 に答える 7

79

fread(buf, 1000, 1, stream)との違いはfread(buf, 1, 1000, stream)、ファイルが小さい場合、最初のケースでは 1000 バイトのチャンクを 1 つだけ取得するか、何も取得しないことです。2 番目のケースでは、ファイル内のすべてを 1000 バイト未満および最大で取得します。

于 2008-11-17T16:16:58.883 に答える
23

freadの実装方法に基づいています。

単一のUNIX仕様は言う

オブジェクトごとに、サイズ呼び出しが fgetc() 関数に対して行われ、その結果が読み取られた順序で、オブジェクトを正確にオーバーレイする unsigned char の配列に格納されます。

fgetcには次のメモもあります。

fgetc() はバイト単位で動作するため、複数のバイトから構成される文字 (または「マルチバイト文字」) を読み取るには、fgetc() を複数回呼び出す必要がある場合があります。

もちろん、これは UTF-8 のような派手な可変バイト文字エンコーディングよりも前のことです。

SUS は、これが実際には ISO C 文書から取られていることに注目しています。

于 2008-11-17T16:19:39.267 に答える
15

これは純粋な推測ですが、当時(一部はまだ存在しています)、多くのファイルシステムはハードドライブ上の単純なバイトストリームではありませんでした。

多くのファイルシステムはレコードベースであったため、このようなファイルシステムを効率的に満たすには、アイテム(「レコード」)の数を指定して、fwrite/freadがバイトストリームだけでなくレコードとしてストレージを操作できるようにする必要があります。

于 2010-09-19T02:32:15.607 に答える
9

ここで、これらの関数を修正します。

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);
}

fread()/へのパラメータの理論的根拠についてはfwrite()、K&R のコピーをずっと前に紛失したので、推測するしかありません。ありそうな答えは、Kernighan と Ritchie が、バイナリ I/O を実行することはオブジェクトの配列に対して最も自然に行われるだろうと単純に考えたということだと思います。また、一部のアーキテクチャでは、ブロック I/O の方が実装が高速で簡単であるなどと考えていた可能性があります。

C 標準では、および がfread()およびfwrite()で実装されることが規定されていますが、この標準は、K&R によって C が定義されてからずっと後に存在したこと、fgetc()および標準で規定されていることは元の設計者のアイデアには含まれていなかった可能性があることを思い出してください。fputc()K&R の「C プログラミング言語」で述べられていることは、言語が最初に設計されたときと同じではない可能性さえあります。

fread()最後に、 「The Standard C Library」でPJ Plauger が述べていることは次のとおりです。

size(2 番目の) 引数が 1 より大きい場合、関数が報告する文字数を超えて追加の文字を読み取るかどうかを判断できませんsize - 1fread(buf, 1, size * n, stream);原則として、代わりに as として関数を呼び出すほうがよいでしょう。fread(buf, size, n, stream);

fread()基本的に、彼は のインターフェイスが壊れていると言っています。fwrite()彼は、「書き込みエラーは一般的にまれであるため、これは大きな欠点ではありません」と述べているため、私は同意しません。

于 2008-11-17T17:46:10.543 に答える
3

ファイル I/O が実装された方法に戻る可能性があります。(当時)一度にすべてを書き込むよりも、ブロック単位でファイルに書き込み/読み取りを行う方が高速だった可能性があります。

于 2008-11-17T16:21:29.933 に答える
-2

Cには関数のオーバーロードがないためだと思います。いくつかある場合、サイズは冗長になります。しかし、C では、配列要素のサイズを決定することはできません。指定する必要があります。

このことを考慮:

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

fwrite がバイト数を受け入れる場合、次のように記述できます。

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

ただ、効率が悪いです。システムコールは sizeof(int) 倍になります。

考慮すべきもう 1 つの点は、通常、配列要素の一部をファイルに書き込むことは望ましくないということです。整数全体が必要か、何も必要ありません。fwrite は、正常に書き込まれた要素の数を返します。要素の下位 2 バイトだけが書き込まれていることがわかったら、どうしますか?

一部のシステムでは (アラインメントのために)、コピーを作成してシフトしないと整数の 1 バイトにアクセスできません。

于 2012-04-18T11:20:58.387 に答える