2009-09-01 13 views
3

XMLファイルを排他的に開き、変更を加えて保存する必要があります。XMLファイルを排他的にオープン/変更しますか?

私はそれを開いて、そのようにかなり簡単に修正を行うことができます。

DataSet ds = new DataSet(); 
ds.ReadXml(filename); 

DataTable table = ds.Tables[0]; 
DataRow[] rows = table.Select("Inventory== 1"); 
DataRow row = rows[0]; 
row["Inventory"] = "2"; 
ds.WriteXml(filename); 

すべてが素晴らしい作品が、それはファイルをロックしません。私は絶対にファイルがロックされている必要があります。

私はストリームとそれを試してみましたので:

FileStream stream = File.Open(filename, FileMode.Open, FileAccess.ReadWrite, FileShare.None); 

DataSet ds = new DataSet(); 
ds.ReadXml(stream); 

DataTable table = ds.Tables[0]; 
DataRow[] rows = table.Select("Inventory== 1"); 
DataRow row = rows[0]; 
row["Inventory"] = "2"; 
ds.WriteXml(stream); 
stream.Close(); 

専用のファイルを開きますが、それは保存するとき、それは時間の終わりにXMLを追加し、それを上書きするので、私はありません以下のようなもので終わる:

<Widgets> 
    <Widget Code="5" Number="10" Inventory="1" /> 
    <Widget Code="6" Number="11" Inventory="15" /> 
    <Widget Code="7" Number="12" Inventory="22" /> 
</Widgets> 
<Widgets> 
    <Widget Code="5" Number="10" Inventory="2" /> 
    <Widget Code="6" Number="11" Inventory="15" /> 
    <Widget Code="7" Number="12" Inventory="22" /> 
</Widgets> 

私が欲しいのです:

<Widgets> 
    <Widget Code="5" Number="10" Inventory="2" /> 
    <Widget Code="6" Number="11" Inventory="15" /> 
    <Widget Code="7" Number="12" Inventory="22" /> 
</Widgets> 

は、私は、ファイルを開くことができ知っているとのu私はファイルメソッドを1行ずつ解析して変更を加えますが、もっとエレガントなものを望んでいました。 ReadXmlを使用してファイルをロードする最初の方法は、ファイルの変更は問題ありませんが、ファイルを排他的に開くためのオプションはありません。何か不足していますか?

答えて

5

、あなたはファイルの先頭に、ストリームの頭をリセットして消去する必要があります置換テキストが元のコンテンツよりも短い場合に既存のコンテンツを上書きする既存のコンテンツ。 ds.writeXml前にこれを置いてみてください。

stream.Seek(0, SeekOrigin.Begin); 
stream.SetLength(0); 

最初の行は、ヘッドを動かし、何をしてテキストを交換することは、元のテキストよりも短い場合、あなたはで余分な文字を持っていないので、第二はファイルを切り捨て終わり。

Reed Copseyが指摘しているように、最初に書き込みを行い、次にストリームのPositionメンバーに長さを設定する方がよいでしょう。置き換えられるテキストが同じ長さの場合には効果がないためですまたは置き換えられたテキストよりも長くなります。これはわずかに効率的です。

+0

素晴らしい!私はそれが私が行方不明だった単純なものでなければならないことを知っていた! – BDW

+0

@Walt W:新しいデータを書き込んだ後にsetlengthを呼び出すこともできます。これはより効果的です(長い場合は効果がなく、短い場合はhteの長さを1回だけリセットします書く...) –

+0

@Reed Copsey:これは本当です。 –

6

あなたはストリームでそれを行うことができますが、あなたが書き込み前にストリームをリセットする必要があります:あなたのストリームで

using(FileStream stream = File.Open(filename, FileMode.Open, FileAccess.ReadWrite, FileShare.None)) 
{ 
    DataSet ds = new DataSet(); 
    ds.ReadXml(stream); 

    DataTable table = ds.Tables[0]; 
    DataRow[] rows = table.Select("Inventory== 1"); 
    DataRow row = rows[0]; 
    row["Inventory"] = "2"; 

    // Reset the stream here to the beginning of the file! 
    stream.Seek(0, SeekOrigin.Begin); 
    ds.WriteXml(stream); 
    // Reset the length of the stream prior to closing it, in case it's shorter than it used to be... 
    stream.SetLength(stream.Position); 
} 
+1

新しいxmlが古いxmlよりも短い場合はどうなりますか? –

+0

ファイルの先頭から探しているだけで、データがファイルの先頭から書き込まれていることを確認してください。すなわち、新しいデータが以前のデータよりも多いかまたは等しいと仮定して、前のデータを上書きするだろうか? –

+1

@ Walt W:+1。私はSetLength(...)呼び出しを入れるのを忘れていました。それは私の編集後、今働くでしょう。書き込む前に長さを0に設定するか、書き込み後に長さを設定する必要があります。 –

関連する問題