[C#] File.Create 鎖定檔案

由於很久沒有寫Stream.IO 的相關程式,剛好今天有一個需求是Parser 文件,「判斷檔案是否存在,不存在就建立新的檔案,存在就寫檔」,結果碰到一個寫檔入門常見的錯誤,

類型 ‘System.IO.IOException’ 的未處理例外狀況發生於 mscorlib.dll 其他資訊: 由於另一個處理序正在使用檔案 ‘C:\Users\Administrator\Desktop\xxxx.xml’,所以無法存取該檔案。

直覺反應這是串流沒有被正常關閉,導致另一個串流想要IO的時候被Lock 住了。

程式範例:

//檔案路徑
string filePath = string.Format("{0}\\{1}.xml", Directory.GetCurrentDirectory(), DateTime.Now.ToString("HH-mm-ss"));
//判斷檔案是否存在,不存在就開一個新檔案
if (!File.Exists(filePath))
{
File.Create(filePath);
}
//開始寫檔
using (StreamWriter sw = new StreamWriter(filePath))
{
sw.WriteLine("寫檔成功");
}

看起來很直覺,且還有使用好寫法「[C#] using statement(陳述式) 資源(IO)控管好寫法!」,

但為何會出現‘System.IO.IOException’,而且神奇的是“檔名”固定的條件下,程式重開後就不會有這個錯誤了!

依據這個線索,發現有問題的是File.Create(),官方文件有寫道 File.Create() 後會回傳 FileStream,也就是說,若你沒有接住這個FileStream, 在程式執行期間,這個資源是被Lock住的;換句話說,因為你沒接住這個FileStream,你也無法操控它並且釋放。

應改用以下寫法:

//檔案路徑
string filePath = string.Format("{0}\\{1}.xml", Directory.GetCurrentDirectory(), DateTime.Now.ToString("HH-mm-ss"));
//判斷檔案是否存在,不存在就開一個新檔案
if (!File.Exists(filePath))
{
using (FileStream fs = File.Create(filePath))
{
}
}
//開始寫檔
using (StreamWriter sw = new StreamWriter(filePath))
{
sw.WriteLine("寫檔成功");
}

或是:

//檔案路徑
string filePath = string.Format("{0}\\{1}.xml", Directory.GetCurrentDirectory(), DateTime.Now.ToString("HH-mm-ss"));
//判斷檔案是否存在,不存在就開一個新檔案
if (!File.Exists(filePath))
{
using (FileStream fs = File.Create(filePath))
{
}
}
//開始寫檔
using (StreamWriter sw = new StreamWriter(filePath))
{
sw.WriteLine("寫檔成功");
}

另外,大家應該可以發現,上述的程式碼都有使用 StreamWriter ,

其實很像從頭到尾,都不需要使用File.Create()來開新檔案,StreamWriter 本上就會判斷檔案是否存在,不存在就建立新的檔案,

所以程式法簡略成這樣即可:

//檔案路徑
string filePath = string.Format("{0}\\{1}.xml", Directory.GetCurrentDirectory(), DateTime.Now.ToString("HH-mm-ss"));
//開始寫檔
using (StreamWriter sw = new StreamWriter(filePath,true))
{
sw.WriteLine("寫檔成功");
}

所以還是套一句老話,用任何工具之前請先熟悉他。

本文也發表於Harry’s Tech World

作者: Harry's Tech World

嗨,我是Harry,在叡揚資訊技術開發中心擔任程式分析師, 在公司負責產品開發並且協助解決同仁碰到的問題, 技術的部分主要專研 MVC、NHibernate 與 Spring ,.Net 相關技術也都有著墨一些, 個人喜歡分享自己在開發上的經驗,所以會把碰到的問題分享在部落格上, 有問題也歡迎聯絡我喔!

發表迴響

你的電子郵件位址並不會被公開。 必要欄位標記為 *