2009-09-01 4 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); 

을하지만, 파일을 잠그지 않습니다. 나는 절대적으로 파일을 잠글 필요가있다.

그래서 나는 스트림과 그것을 시도 : 독점적으로 파일을 열고, 그러나 저장할 때, 그것은 시간의 마지막에 XML을 추가

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(); 

, 그것을 덮어 쓰지 않습니다, 그래서 같은 끝낼 :

<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> 

은 내가 파일을 열 수 있습니다 알고 유 se File 메서드를 한 줄 한 줄씩 파싱하고 변경합니다 ...하지만 좀 더 우아 해지기를 바랬습니다. ReadXml을 사용하여 파일을로드하는 첫 번째 방법은 파일 수정만으로 충분하지만 파일을 단독으로 여는 옵션은없는 것으로 보입니다. 내가 놓친 게 있니?

답변

5

대체 텍스트가 원본 콘텐츠보다 짧은 경우 기존 데이터를 덮어 쓰려면 기존 콘텐츠를 삭제하십시오. ds.writeXml 전에이 배치보십시오 :

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

첫 번째 줄은 머리를 이동, 당신이 함께 텍스트를 교체하는 것은 원래의 텍스트보다 짧은 경우, 당신은에없는 문자가되지 않도록 두 번째 파일을 자릅니다 끝.

Reed Copsey가 지적했듯이 먼저 쓰기를 수행 한 다음 길이를 스트림의 Position 멤버로 설정하는 것이 좋습니다. 교체하는 텍스트가 동일한 길이 인 경우 효과가 없으므로 또는 대체 된 텍스트보다 길어서 약간 더 효율적일 수 있습니다.

+0

좋습니다! 나는 그것이 내가 놓치고 있었던 것이 단순해야만한다는 것을 알았다! – BDW

+0

@Walt W : 새로운 데이터를 작성한 후에도 setlength를 호출 할 수 있습니다.이 방법은 잠재적으로 더 효과적입니다 (더 길면 효과가 없으므로 길이가 짧으면 hte 길이를 한 번만 재설정합니다. 쓰기 ...) –

+0

@ 리치 복사 : 사실입니다. –

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으로 설정하거나 쓰기 후에 길이를 설정해야합니다. –

관련 문제