4

入力ファイルと出力ファイルの両方に同じファイル名を使用する可能性をプログラムに追加して、入力ファイルを置き換えることを考えています。

処理されたファイルは非常に大きい可能性があるため、最初にファイルを開き、それを削除して新しいファイルを作成するのが最善の解決策だと思います。つまり、次のようになります。

/* input == output in this case */
FILE *inf = fopen(input, "r");
remove(output);
FILE *outf = fopen(output, "w");

(もちろんエラーハンドリングも追加)

remove()すべてのシステムで開いているファイルを削除できるわけではないことを認識しており、その場合に失敗する限り、それは許容されます。

開いているファイルを削除して、その内容を読み取れないシステムがないか心配です。

C99 標準では、その場合の動作を「実装定義」として指定しています。SUSはそのケースについてさえ言及していません。

あなたの意見/経験は何ですか? 心配する必要はありますか?そのような解決策を避けるべきですか?

編集: これは主要な機能ではなく、ユーザーが入力ファイルと出力ファイルの両方に同じファイル名を指定した場合の「最後の手段」であることに注意してください。

編集: わかりました、もう 1 つ質問があります: この特定のケースでは、私が提案した解決策は、出力ファイルを書き込み専用で開くだけでなく、より多くの悪を実行できる可能性があります (つまり、上記のように、remove()呼び出しなしで)。

4

3 に答える 3

4

いいえ、安全ではありません。ファイルシステムでは機能するかもしれませんが、他のシステムでは失敗します。または、断続的に失敗する場合があります。それは本当にあなたのオペレーティングシステムとファイルシステムに依存します. Solaris の詳細については、ファイル ローテーションに関するこの記事を参照してください。

GNU sed の「--in-place」オプションを見てください。このオプションは、出力を一時ファイルに書き込んでから、元のファイルをコピーすることで機能します。これが唯一の安全で互換性のある方法です。

また、停電やプロセスの強制終了により、プログラムがいつでも失敗する可能性があることも考慮する必要があります。これが発生すると、元のファイルが失われます。さらに、参照カウントを持つファイル システムの場合、入力ファイルが閉じられるまで両方のファイルがディスク上に存在する必要があるため、一時ファイル ソリューションよりもスペースを節約できません。

ファイルが巨大で、スペースが貴重で、開発者の時間が安価な場合は、読み取り/書き込み用に単一ファイルを開き、書き込みポインターが読み取りポインターを超えないようにすることができます。

于 2009-09-02T23:12:53.840 に答える
4

開いているファイルを削除できることを認識しているすべてのシステムは、ファイル ノードの何らかの形式の参照カウントを実装しています。そのため、ファイルを削除するとディレクトリ エントリが削除されますが、ファイル ノード自体には、開いているファイル ハンドルからの参照が 1 つあります。このような実装では、ファイルを削除しても、それを読み続ける能力に影響しないことは明らかであり、この動作を実装する他の合理的な方法を想像するのは難しいと思います.

于 2009-09-02T22:51:58.610 に答える
1

私は常にこれを Linux/Unix で動作させてきました。Windows、OS/2、または (身震いする) DOS では絶対に使用しないでください。他に気になるプラットフォームはありますか?

この動作は、一時ディスク領域を使用する場合に実際に役立ちます。ファイルを読み取り/書き込み用に開き、すぐに削除します。プログラムの終了時に(停電を含む何らかの理由で)自動的にクリーンアップされ、他の人がそれを監視することをはるかに困難にします(ただし、不可能ではありません)(そのプロセスへの読み取りアクセス権がある場合、 /proc は手がかりを与えることができます) .

于 2009-09-02T22:57:26.647 に答える