C fopen vs open


219

使用したい理由がありますか(構文上の理由以外)

FILE *fdopen(int fd, const char *mode);

または

FILE *fopen(const char *path, const char *mode);

の代わりに

int open(const char *pathname, int flags, mode_t mode);

Linux環境でCを使用する場合


もしかしてfdopenopenfopenopen
user7116 2009年

fdopenではなく、fopenを意味するのではないですか?
2009年

9
fopen標準Cライブラリの一部ですが、openありません。fopen移植可能なコードを書くときに使用します。
アジズ

はい、私はfopenを意味しました。更新したばかりですが、同じ原則が当てはまると思います。
LJM

6
@Aziz openはPOSIX関数です。
dreamlax 2009年

回答:


242

最初に、がオプションであり、が他の可能な選択肢であるfdopen場合に使用する特別な理由はありません。必要な場合は、最初からファイルを開くために使用するべきではありませんでした。そのため、そのリストに含めることは、他のものとあまり似ていないため、正しくなく、混乱しています。ここで重要な違いはC標準とOS固有のファイル記述子の間であるため、ここでは無視します。fopenopenopenFILE *fdopenFILE *

fopen代わりに使用する主な理由は4つありますopen

  1. fopenでは、バッファリングIOが提供されますopen。これは、実際の処理よりもはるかに高速になる場合があります。
  2. fopen ファイルがバイナリモードで開かれていない場合は行末変換を行います。これは、プログラムが非UNIX環境に移植された場合に非常に役立ちます(ただし、世界はLFのみに収束しているように見えます(IETFテキストベースのネットワークを除く)。 SMTPやHTTPなどのプロトコル))。
  3. A FILE *を使用するfscanfと、他のstdio関数を使用できます。
  4. ANSI Cのみをサポートし、open関数をサポートしない他のプラットフォームにコードを移植する必要がある場合があります。

私の意見では、行末の翻訳はあなたを助けるよりも頻繁に邪魔になり、の解析fscanfは非常に弱いので、あなたは必然的にそれをより有用な何かのために放棄することになります。

また、Cをサポートするほとんどのプラットフォームにはopen関数があります。

それはバッファリングの問題を残します。主に順次ファイルの読み取りまたは書き込みを行う場所では、バッファリングのサポートが非常に役立ち、速度が大幅に向上します。しかし、データがファイルにあると予期しても、データがファイルに含まれないという興味深い問題が発生する可能性があります。あなたは、fcloseまたはfflush適切な時に覚えておく必要があります。

シークを行っている場合(別名fsetposまたはfseekその2番目は、標準に準拠した方法で使用するには少しトリッキーです)、バッファリングの有用性はすぐに低下します。

もちろん、私のバイアスは、私がソケットFILE *を頻繁に使用する傾向があることであり、非ブロッキングIO(まったく合理的な方法で完全にサポートされていない)をバッファリングなしで頻繁に実行したいという事実があります複雑な構文解析要件があると、私の認識が本当に変わります。


4
私はあなたの経験に疑問を投げかけるつもりはありませんが、これについて少し詳しく説明してほしいと思います。組み込みのバッファリングが邪魔になると思うアプリケーションの種類は何ですか?正確には何が問題ですか?
Emil H

1
最後の段落を見ませんでした。妥当なポイント、私見。私が知る限り、質問はファイルIOに関するものでした。
Emil H

7
バッファリングが邪魔になるタイミングを明確にする。シークを使用するときです。どんなコマンドでは、次の読み取りが(fgetsfgetcfscanffread)、常にバッファ(4K、8Kまたはものは何でも設定)の全体の大きさを読み込みます。ダイレクトI / Oを使用すると、それを回避できます。その場合preadは、シーク/読み取りペアの代わりに使用するほうが適切です(2ではなく1 syscall)。
パトリックSchlüter

2
割り込みread()write()呼び出しの処理は、libcファミリーの関数を使用する5番目の便利な理由です。
nccc 2012

3
@ m-ric:まあ、それはやや無関係な質問ですが、はい。をサポートするすべてのプラットフォームは、aを取りioctlfileno呼び出しでFILE *使用できる数値を返す呼び出しもサポートしioctlます。注意してください。FILE *関連する呼び出しはioctl、基になるファイル記述子について何かを変更するためにを使用して意外にも相互作用することがあります。
全知

53

open()低レベルのos呼び出しです。fdopen()OSレベルのファイル記述子を、C言語のより高いレベルのFILE抽象に変換します。バックグラウンドでfopen()呼び出しopen()、FILEポインターを直接提供します。

生のファイル記述子ではなくFILEオブジェクトを使用することにはいくつかの利点があります。これには、使いやすさだけでなく、組み込みバッファリングなどの他の技術的な利点も含まれます。特に、バッファリングは一般的にかなり大きなパフォーマンス上の利点をもたらします。


3
バッファリングされた「f ...」バージョンのopenを使用することに不利な点はありますか?
LJM

5
@L。Moserはい、すでにデータをバッファリングしているため、追加のバッファにより、不必要なコピーとメモリのオーバーヘッドが追加されます。
Michael Aaron Safyan、2009年

6
実際には他の欠点があります。fopen()は、ファイルを開くときに同じレベルの制御を提供しません。たとえば、作成権限、共有モードなどです。通常open()、バリアントは、オペレーティングシステムが実際に提供するものに近い、より多くの制御を提供します
Matt Joiner

2
mmapファイルを変更して通常のI / Oで変更する極端なケースもあります(プロジェクトで実際にそうするように聞こえるので、信じられないことですが、実際の正当な理由で)、バッファリングが邪魔になります。
PatrickSchlüter10年

また、readahead()を使用してファイルをページキャッシュにプリロードするためにopen()を使用するなど、他のシステム関数を使用することもできます。経験法則は「open()が絶対に必要でない限り、fopenを使用する」だと思います。open()を使用すると、実際には高度な機能(O_ATIMEの設定など)を実行できます。
Tomas Pruzina 2013年

34

fopen vs Cで開く

1)fopenであるライブラリ関数ながら、openあるシステムコール

2)fopen提供緩衝IO高速に比較さopenれるある非バッファ

3)fopenであるポータブルしばらくopenないポータブルオープンは、環境固有のものです)。

4)FILE構造体(FILE *)fopenへのポインターを返します。ファイルを識別する整数を返します。 open

5)A FILE *を使用すると、fscanfおよびその他のstdio関数を使用できます。


9
openPOSIX標準であるため、移植性が高い
osvein

12

使用することopenが実際のパフォーマンス上の利点であるアプリケーションの0.1%の一部でない限り、実際に使用しない理由はありませんfopen。これまでのようにfdopen関係しているあなたはファイルディスクリプタで遊んでされていない場合、あなたはその呼び出しを必要としません。

スティックfopenとメソッドのその家族(fwritefreadfprintf、ら)、あなたは非常に満足するでしょう。同様に重要なことには、他のプログラマーもあなたのコードに満足するでしょう。


11

あなたが持っている場合はFILE *、次のような機能を使用することができfscanffprintfそしてfgetsあなただけのファイル記述子を持っている場合は、入力と出力ルーチン制限(しかしそう速く)しているなどreadwriteなど


7

open、read、writeを使用すると、信号の相互作用について心配する必要があります。

呼び出しがシグナルハンドラーによって中断された場合、関数は-1を返し、errnoをEINTRに設定します。

したがって、ファイルを閉じる適切な方法は

while (retval = close(fd), retval == -1 && ernno == EINTR) ;

4
の場合close、これはオペレーティングシステムによって異なります。Linux、AIX、およびその他のいくつかのオペレーティングシステムでループを実行するのは正しくありません。
strcat

さらに、読み取りと書き込みを使用すると同じ問題が発生します。つまり、入出力を完全に処理する前に信号によって中断され、プログラマーはそのような状況を処理する必要がありますが、freadとfwriteは信号の中断を適切に処理します。
Marcelo

6

open()Unixベースのシステムに固有のシステムコールであり、ファイル記述子を返します。write()もう1つのシステムコールであるファイル記述子に書き込むことができます。
fopen()ファイルポインタを返すANSI C関数呼び出しであり、他のOSに移植可能です。を使用してファイルポインタに書き込むことができますfprintf

Unixの場合:次
を使用して、ファイル記述子からファイルポインタを取得できます。

fP = fdopen(fD, "a");

以下を使用して、ファイルポインタからファイル記述子を取得できます。

fD = fileno (fP);

4

open()は、fopen()ファミリー関数のそれぞれの終わりに呼び出されます。open()はシステムコールであり、fopen()はユーザーが使いやすいラッパー関数としてライブラリによって提供されます


2

fopenがfopen fgetcを実行するたびに二重読み取りを引き起こしていたため、アプリケーションのfopen()からopen()に変更しました。二重読み取りは、私が達成しようとしていたことを破壊しました。open()は、あなたが求めていることを実行しているように見えます。


2

開くために必要なフラグにも依存します。上記のように、書き込みと読み取り(および移植性)の使用法に関しては、f *を使用する必要があります。

ただし、基本的に標準のフラグ(rwや追加フラグなど)よりも多くのフラグを指定する場合は、プラットフォーム固有のAPI(POSIX openなど)またはこれらの詳細を抽象化するライブラリを使用する必要があります。C標準には、そのようなフラグはありません。

たとえば、ファイルが存在する場合にのみ、ファイルを開くことができます。作成フラグを指定しない場合、ファイルは存在している必要があります。作成に排他を追加すると、ファイルが存在しない場合にのみファイルが作成されます。他にもたくさんあります。

たとえば、Linuxシステムでは、sysfsを通じて公開されるLEDインターフェイスがあります。ファイルを介してledの明るさを公開します。数値を0〜255の範囲の文字列として読み書きします。もちろん、そのファイルを作成するのではなく、存在する場合にのみファイルに書き込みます。すばらしい点は、fdopenを使用して、標準の呼び出しでこのファイルを読み書きすることです。


0

fopenを使用してファイルを開く
前に、ディスク上のファイルから情報を読み取る(または書き込む)には、ファイルを開く必要があります。関数fopenを呼び出したファイルを開きます。

1.firstly it searches on the disk the file to be opened.
2.then it loads the file from the disk into a place in memory called buffer.
3.it sets up a character pointer that points to the first character of the buffer.

これはfopen関数の動作方法で
あり、プロセスのバッファリング中にいくつかの原因があり、タイムアウトになる場合があります。そう比較しながらのfopenする(ハイレベルI / O)を開く(低レベルI / O)システム・コールを、それがより速く、より適切であるのfopen


fopenよりも速く開いていますか?
2016

はい、openはシステムコールです。これはfopenよりも高速です-比較すると@obayhan
prashad
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.