すでに開いているファイルを .net StreamReader で開くにはどうすればいいですか? 質問する

すでに開いているファイルを .net StreamReader で開くにはどうすればいいですか? 質問する

テストベンチの一部として使用している.csvファイルがいくつかあります。問題なく開いて読み取ることができます。ない限りすでに Excel でファイルを開いている場合は、次のメッセージが表示されますIOException

System.IO.IOException: プロセスは、別のプロセスによって使用されているため、ファイル 'TestData.csv' にアクセスできません。

これはテストベンチからの抜粋です:

using (CsvReader csv = new CsvReader(new StreamReader(new FileStream(fullFilePath, FileMode.Open, FileAccess.Read)), false))
{
    // Process the file
}

これは StreamReader の制限でしょうか? 他のアプリケーション (たとえば Notepad++) でファイルを開くことができるので、O/S の問題ではないはずです。他のクラスを使用する必要があるのでしょうか? これを回避する方法 (Excel を閉じる以外に!) をご存知の方がいらっしゃいましたら、大変助かります。

ベストアンサー1

Jaredが言うように、ファイルを開いている他のエンティティが共有読み取りを許可しない限り、これを行うことはできません。Excelは、書き込み用に開いているファイルであっても共有読み取りを許可します。したがって、ファイルストリームを次のように開く必要があります。ファイル共有.読み取り書き込みパラメータ。

FileShareパラメータはよく誤解されます。他のファイルのオープン者が実行できる操作です。これは、過去のオープン者だけでなく将来のオープン者にも適用されます。FileShare は、以前のオープン者 (Excel など) に対する遡及的な禁止ではなく、現在のオープンまたは将来のオープンで違反してはならない制約であると考えてください。

現在のファイルを開く試みの場合、FileShare.Readは「以前にこのファイルを開いたユーザーがいる場合にのみ、このファイルを開いてください」と表示します。のみExcelで書き込み用に開かれているファイルにFileShare.Readを指定すると、あなたのExcelでは開いているため、制約に違反するため、開くことができません。執筆用

Excelはファイルを書き込み用に開いているため、あなたの成功するためにオープンします。FileShare パラメータを別の方法で考えると、「他の人のファイル アクセス」を指定します。

ここで、現在他のアプリによって開かれていないファイルを開くという別のシナリオを想定します。FileShare.Read は、「今後ファイルを開くユーザーは、読み取りアクセスでのみファイルを開くことができます」と述べています。

論理的には、これらのセマンティクスは理にかなっています。FileShare.Read は、他のユーザーが既にファイルに書き込んでいる場合はそのファイルを読み取りたくないこと、また、自分が既にファイルを読み取っている場合は他のユーザーにそのファイルを書き込ませたくないことを意味します。FileShare.ReadWrite は、他のユーザーがファイルに書き込んでいる場合でもファイルを読み取る意思があり、自分がファイルを読み取っている間に他のユーザーがファイルを書き込んでも問題ないことを意味します。

いかなる場合でも、複数の書き込みは許可されません。FileShare はデータベースの IsolationLevel に似ています。ここで必要な設定は、必要な「一貫性」の保証によって異なります。

例:

using (Stream s = new FileStream(fullFilePath, 
                                 FileMode.Open,
                                 FileAccess.Read,
                                 FileShare.ReadWrite))
{
  ...
}

または、

using (Stream s = System.IO.File.Open(fullFilePath, 
                                      FileMode.Open, 
                                      FileAccess.Read, 
                                      FileShare.ReadWrite))
{
}

補遺:

System.IO.FileShare に関するドキュメント少し薄いです。正確な事実を知りたい場合は、Win32 CreateFile 関数のドキュメントこれは、FileShare の概念をよりよく説明しています。

おすすめ記事