由於很久沒有寫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))
{
File.Create(filePath).Close();
}
//開始寫檔
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("寫檔成功");
}
所以還是套一句老話,用任何工具之前請先熟悉他。