我已经实现了一个csv文件构建器,它接受一个xml文档对其应用xsl转换并将其附加到文件中。对文件进行多次写入时发生IOException
public class CsvBatchPrinter : BaseBatchPrinter
{
public CsvBatchPrinter() : base(".csv")
{
RemoveDiatrics = false;
}
protected override void PrintDocuments(System.Collections.Generic.List<XmlDocument> documents, string xsltFileName, string directory, string tempImageDirectory)
{
base.PrintDocuments(documents, xsltFileName, directory, tempImageDirectory);
foreach (var file in new DirectoryInfo(tempImageDirectory).GetFiles())
{
var destination = directory + file.Name;
if (!File.Exists(destination))
file.CopyTo(destination);
}
}
protected override void PrintDocument(XmlDocument document, string xsltFileName, string directory, string tempImageDirectory)
{
StringUtils.EscapeQuotesInXmlNode(document);
if (RemoveDiatrics)
{
var docXml = StringUtils.RemoveDiatrics(document.OuterXml);
document = new XmlDocument();
document.LoadXml(docXml);
}
using (var writer = new StreamWriter(string.Format("{0}{1}{2}", directory, "batch", FileExtension), true, Encoding.ASCII))
{
Transform(document, xsltFileName, writer);
}
}
public bool RemoveDiatrics { get; set; }
}
我有大量的XML文档添加到这个csv文件,并多次调用它后,它有时抛出IOException The process cannot access the file 'batch.csv' because it is being used by another process.
这是否是某种形式的锁定问题?
难道要解决:
lock(this)
{
using (var writer = new StreamWriter(string.Format("{0}{1}{2}", directory, "batch", FileExtension), true, Encoding.ASCII))
{
Transform(document, xsltFileName, writer);
}
}
编辑:
这里是我的堆栈跟踪:
at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)
at System.IO.FileStream.Init(String path, FileMode mode, FileAccess access, Int32 rights, Boolean useRights, FileShare share, Int32 bufferSize, FileOptions options, SECURITY_ATTRIBUTES secAttrs, String msgPath, Boolean bFromProxy)
at System.IO.FileStream..ctor(String path, FileMode mode, FileAccess access, FileShare share, Int32 bufferSize, FileOptions options)
at System.IO.StreamWriter.CreateFile(String path, Boolean append)
at System.IO.StreamWriter..ctor(String path, Boolean append, Encoding encoding, Int32 bufferSize)
at System.IO.StreamWriter..ctor(String path, Boolean append, Encoding encoding)
at Receipts.Facade.Utilities.BatchPrinters.CsvBatchPrinter.PrintDocument(XmlDocument document, String xsltFileName, String directory, String tempImageDirectory) in CsvBatchPrinter.cs:line 37
at Receipts.Facade.Utilities.BatchPrinters.BaseBatchPrinter.PrintDocuments(List`1 documents, String xsltFileName, String directory, String tempImageDirectory) in BaseBatchPrinter.cs:line 30
at Receipts.Facade.Utilities.BatchPrinters.CsvBatchPrinter.PrintDocuments(List`1 documents, String xsltFileName, String directory, String tempImageDirectory) in CsvBatchPrinter.cs:line 17
at Receipts.Facade.Utilities.BatchPrinters.BaseBatchPrinter.Print(List`1 documents, String xsltFileName, String destinationDirectory, String tempImageDirectory) in BaseBatchPrinter.cs:line 23
at Receipts.Facade.Modules.FinanceDocuments.FinanceDocumentActuator`2.printXmlFiles(List`1 xmlDocuments, String tempImagesDirectory) in FinanceDocumentActuator.cs:line 137
和我的基类:
public abstract class BaseBatchPrinter : IBatchPrinter
{
private static readonly ILog Log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
protected readonly string FileExtension;
protected BaseBatchPrinter(string fileExtension)
{
FileExtension = fileExtension;
}
public void Print(List<XmlDocument> documents, string xsltFileName, string destinationDirectory, string tempImageDirectory)
{
Log.InfoFormat("Printing to directory: {0}", destinationDirectory);
PrintDocuments(documents, xsltFileName, destinationDirectory, tempImageDirectory);
}
protected virtual void PrintDocuments(List<XmlDocument> documents, string xsltFileName, string directory, string tempImageDirectory)
{
foreach (var document in documents)
{
PrintDocument(document, xsltFileName, directory, tempImageDirectory);
}
}
/// <summary>
/// Needs to Call Transform(XmlDocument document, string xsltFileName, string directory)
/// </summary>
protected abstract void PrintDocument(XmlDocument document, string xsltFileName, string directory, string tempImageDirectory);
protected void Transform(XmlDocument document, string xsltFileName, StreamWriter writer)
{
//TODO: look into XslCompiledTransform to replace the XslTransform
var xslTransform = new XslTransform();
xslTransform.Load(xsltFileName);
xslTransform.Transform(createNavigator(document), null, writer);
}
protected string CreateFileName(string directory, XmlDocument doc)
{
var conId = createNavigator(doc).SelectSingleNode(Config.SELECT_CONSTITUENT_ID_XPATH).Value;
return string.Format(@"{0}{1}{2}", directory, conId, FileExtension.IndexOf('.') > -1 ? FileExtension : "." + FileExtension);
}
protected XPathNavigator createNavigator(XmlDocument document)
{
return document.DocumentElement == null ? document.CreateNavigator() : document.DocumentElement.CreateNavigator();
}
}
干杯。
你知道你不是在调用你的CreateFilename()方法吗?如果这是意图,那么也许从最近的经验来看,如果意图是将每个文档写入同一个文件,那么我会在using块中添加一个.Close(),即使应该在超出范围时调用Dispose() ,它应该关闭文件。花费没有什么可尝试,并会带你几分钟 – 2009-06-04 01:31:02
西蒙,你应该添加,作为一个答案.... – zonkflut 2009-06-04 02:58:00