2016-11-09 22 views
1

XMLファイルをコンパイルするために長期間実行されるREST APIメソッドがあります。ユーザーはこのコンパイルを開始する要求を行い、基本ファイルが作成され、ユーザーに進行状況を照会するための一意のIDが与えられます。XMLファイルを書き込んでいるときに読む

progress-readingメソッドは、読み取り専用アクセスでファイルを開き、XDocumentオブジェクトをインスタンス化し、その中の要素の数を数えます。

XMLファイルは

using (var fs = new FileStream(filePath, FileMode.Open, FileAccess.ReadWrite, FileShare.Read)) 
{ 
    var xmlDoc = XDocument.Load(fs); 

    foreach (...) 
    { 
     // add the element to xmlDoc 

     xmlDoc.Save(filePath); 
    } 
} 

そしてファイルに、しかし要素

using (var fs = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) 
{ 
    var xmlDoc = XDocument.Load(fs); 

    // count elements 
} 

の数をカウントするためにを読み取るコードでアクセスされ移入コードにはメソッドがあり、例外がスローされますxmlDoc.Save(filePath);

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

私はそれを理解できるように、FileShare.ReadでのFileStreamを開くと、別のプロセスが読み取り専用アクセスでファイルを開くことができます(と私はこれが起こっていると考えている)と同様に読み取り/カウント方法でFileShare.ReadWriteを使用して移入を可能にします書き込みアクセスでファイルを開くプロセス。

上記のコードでは、どちらのプロセスでも私が期待することができないのはなぜですか?

答えて

2

あなたは

xmlDoc.Save(filePath) 

を呼び出すときにファイル名を渡すので、XmlDocumentはあなたが書き込みのために開かれたあなたのfsストリームを使用していません。その代わりに、それはもう一つのストリームを内部的に開きます。これはすでに書き込みのために開かれたストリームが1つあるので失敗します。完全にわからないIRSが必要かかわら

代わりに、ストリームの先頭に追求し、その後

xmlDoc.Save(fs); 

を呼び出すまた、(古い内容を切り捨てるように)保存する前にゼロにストリーム長を設定することがあります。

+0

"古いコンテンツを切り捨てるために保存する前にストリームの長さをゼロに設定することもできます"という提案の理由を説明できますか?ストリームの内容を保存する前にストリームを_length_に0に設定しないでください。または、あなたは現在の位置に長さを設定する必要があると書いていたのでしょうか? – awj

+0

まず、既存のコンテンツを含むストリームを開き、その内容をXDocument(XDocument.Load)に読み込みます。ファイルが1000バイトであったとします。保存する前に、ストリームの長さは1000で、位置は1000です.0の位置を決めて保存します。ここで、新しい文書の長さが900であるとします。XDocument.Saveがストリームの長さ自体を900に設定しないと、新しい文書が900バイト、前の文書が100バイト、合計で1000になります。欲しいです。私はXDocument.Saveが内部的にどのように動作するのか分からないので、私は、保存する前にストリームを切り捨てて、確かめることを提案しました。 – Evk

+0

OK、作成する2点:(1)ファイルに書き込まれる内容は増加するだけです。開いたとき、FileStreamは決してそれよりも短くなることはありません。 (2)これを実装している間に、「ストリームの開始前に位置を移動しようとしました」という例外が発生しています。これは一見無作為な時に起こります - 時には最初のクエリ読み込みの間に、他の時はずっと後に起こります。 – awj

関連する問題