2012-05-28 12 views

答えて

7

あなたの仕事によって異なります。テキストファイルを連続的に読み書きするために、iostreamは間違いなく道のりです。トランザクションセキュリティや非標準デバイスに関するものは、システムに直接アクセスする必要があります(CreateFileまたはopen)。それでも、テキストのシーケンシャル読み込みと書き込みのために、最善の解決策は、streambuf独自に定義する、とのiostreamとそれを使用することです。

fopenが好ましいと思われる文脈は考えられません。

+0

私は力をしたい:)バイナリを書いて読んでください。私は開いていると聞いて、ファイルを作成するのには合わないのですか?これは本当ですか? – Eveler

+1

@Eveler:完全なパワーを望むなら、ファイルを処理するのに最も速いのは、[CreateFileMapping]を使ってファイルを開き、CreateFileMappingでメモリにマップすることです(http: //blogs.msdn.com/b/oldnewthing/archive/2005/05/13/417183.aspx)、[標準C++]から始まる最適化シリーズの一部です(http://blogs.msdn.com/ b/oldnewthing/archive/2005/05/10/415991.aspx)、次に[Win32 optimized code]に移動します(http://blogs.msdn.com/b/oldnewthing/archive/2005/05/19/420038 .aspx)。しかし、ほとんどの場合、単純な標準CとC++はOKです。 –

+3

'fopen'は上位レベルの関数で、C++では' fstream :: open'に置き換えられました。 'CreateFile'と' open'はシステムレベルの関数で、Windowsでは最初の関数、Unixでは2番目の関数です。システムは異なる機能を別々にサポートしているため、まったく同じものを提供するわけではありません。 –

1

ほとんどの場合、C++ではfopenを、C++ではofstreamを使用する方がよいでしょう。 CreateFileは、共有とキャッシングをさらに制御しますが、書式設定機能は提供しません。

+1

したがって、 'CreateFile'を使う必要がある方法で' streambuf'を書いて、両方の利点を得ることができます。 –

+0

私はいつも、IOstreamに新しいソースや宛先を接続するのはとても面倒です。もしあれば、C++はデータライター/リーダにとって純粋な抽象クラスを宣言するのを容易にします。 –

4

あなたは、Windowsのファイル機能によって提供される機能は、(例えばI/Oをオーバーラップ)が必要なければ、その後、私の提案は、よりポータブルであることに加えC.

でC++またはFILEfopenや友人)で入出力ストリームのいずれかで起こっています書式付きの入出力をテキストファイルに使用することもできます.C++では、クラスの出力/入力演算子を簡単にオーバーロードできます。

+2

'std :: streambuf'といくつかの特別な機能(トランザクションの完全性、特殊デバイス、など)。 –

2

OS API関数(CreateFileなど)によって提供される特別な機能が無条件に必要な場合を除き、標準ライブラリ関数(fopenまたはofstreamなど)を使用することをお勧めします。あなたのプログラムはよりポータブルになります。

私はI/Oと、おそらくより細かい粒度のアクセス権を重複していると考えることができCreateFileを使用しての唯一の本当の利点。

+2

Createfileは、260文字を超えるファイルパスを開くことができます。 – Eveler

+0

十分なフェア! +1 – cyco130

2

あなたは、Windowsのファイルメモリマッピングを使用する場合は、CreateFileを使用する必要がありますに(CreateFileMapping APIに渡された、例えばHANDLECreateFileの戻り値です)。また、CreateFileは、CおよびC++標準のファイルAPIよりも高いカスタマイズオプションを提供しています。

移植コードを書く場合、またはWindows固有の機能が必要ない場合は、CおよびC++の標準ファイルAPIは問題ありません。大きなデータを処理する際にいくつかのテストで は、私はC++ I/Oは、生のCファイルAPI対ストリームのいくつかのパフォーマンス・オーバーヘッドを指摘しました。あなたはこのようなケースであることが起こるならば、あなたは、単にいくつかのC++ RAIIクラスの生のCファイルのAPIをラップし、まだC++のコードでそれを使用することができます。

+0

私は4GBから10GB +までの大容量データファイルとmemマッピングを必要とします。 – Eveler

+0

メモリマッピングが必要な場合は、Direct Win32 API呼び出しを使用してC++ RAIIクラスでラップすることができます。 –

0

私は

私をエスケープ何らかの理由で閉鎖された

fopen or CreateFile in Windows

から私の答えをコピーし...

  1. fopenのための定義された方法は(ありません)システムエラーを返しますコード。errnoにアクセスするための未定義の方法があるかもしれませんが、これはシステムのエラーコードと同じでも異なっていてもかまいません。
  2. また、私は今度はあなたがそのような期待する多くのWin64のシステムコールの1に渡すために使用する場合があります(タイプHANDLEの)実際のシステムハンドルにアクセスするための定義された方法があるとは思いません
  3. open()を使用すると、システムハンドル(ウィンドウ上)ではないファイルハンドルが整数で表されます。
  4. エラーの場合、fopen()は例外をスローしません。いくつかのRAIIを取得するには、クラスにラップする必要があります。クラスへ
  5. ラッピングのCreateFile()は、クラスにはfopen()、またはオープンを()ラップよりも高価ではありません。ファイルから同じ問題に苦しんでいるに/読み込み/書き込みにC++の機能(のstd :: ofstreamの、のstd ::はifstream)を使用して
  6. のfopen(): それは誤りで、デフォルトではスローされません
    • 。この機能を有効にするには、いくつかのコンストラクタ引数を使用する代わりに、いくつかのメソッドを呼び出す必要があります。つまり、このクラスを派生させる必要があるRAII(エラーをスローするメンバ/ベースクラスとして使用する) 。
    • 1は、メッセージがあなたのシステムエラーについて何を伝え何を()から返されたスローされた例外の場合、またはシステム・エラー・コードを取得することができる場合それは未定義です。
    • このストリームインターフェイスを使用すると、読み込み元または書き込み先を定義するためのプラグイン可能なインターフェイスはありません。ストリームインターフェイスのオーバーロードは非常に面倒でエラーが発生しやすいです。
  7. プログラミング(に注意を払うか、リターンコードを無視して、手動でクリーンアップコードを書く)のようにCを使用すると、多くの悪の源である(ハート出血を覚えている?)...

結論:

  1. はのCreateFile()/ CloseHandleを()のリソースラッパを書き込みます。リソースラッパーは、コンストラクターでdo-actionを実行し、デストラクタでUndo-actionを実行し、エラーが発生した場合に例外をスローするクラスです。すべてのOS、特にWin64には、このようなシステムコールのペアがたくさんあります。
  2. (C++ 0xの中に)新しいSYSTEM_EXCEPTIONクラスが実際に何をしているのか、システムエラーの例外クラスを書く(のCreateFileの場合には上記のクラスのために使用する()は失敗し、他のすべてのシステムエラーの場合)または調査それが十分であれば。
  3. が潜在的にどこかに書いて、あなたが実装できるようにどこかから読み取るために、独自のインタフェースを定義する...スローシステム例外オブジェクトにシステムエラーを変換し、ReadFile()およびWriteFile()のための機能のラッパーを書きます読み書きするソース/デスティネーションのタイプに依存しない他のもの。
  4. どこかから読み込みをキャッシュしたり、どこかに書き込むことを可能にするキャッシュクラスを書くことは、子供の遊びでもあります。もちろん、キャッシュクラスは、あなたが書いている/読んでいるソース/デスティネーションを知らないでください。

これらの小さなタスクについて怖がってはいけません。あなたは実際にあなたのコードで起こっていることを知っているでしょうし、これらの小さなコードはそれを呼び出すコードに比べて(コード行の量で)無視してください。また、RAIIをすべて使用している場合、これらのユーティリティクラスを呼び出すコードは、RAIIを使用していない場合と比べて大幅に少なくなり、2段階以上の初期化を行い、これらのユーティリティクラスを他のOS用の等価なユーティリティクラスに置き換えることも、子プレイ(UNIXではopen()/ close()/ read()/ write()を使用)です。

そして、前の千年のために、Googleのプログラミングガイドラインを読んではいけません!

関連する問題