문제

XML 문서를 취하는 CSV 파일 빌더를 구현하여 XSL 변환을 적용하여 파일에 추가합니다.

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

이 CSV 파일에 추가 할 XML 문서가 많고 여러 번 호출 한 후에는 때때로 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();
    }
}

건배.

도움이 되었습니까?

해결책 3

여러분의 답변에 감사드립니다.

나는 나를 위해 일하는 솔루션을 생각해 냈습니다. 약간 해킹되지만 그것은 일을합니다.

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

IOException ex = null;
for (var attempts = 0; attempts < 10; attempts++)
{
    ex = tryWriteToFile(document, directory, xsltFileName);
    if (ex == null)
        break;
}

if (ex != null)
    throw new ApplicationException("Cannot write to file", ex);
}

private IOException tryWriteToFile(XmlDocument document, string directory, string xsltFileName)
{
try
{
    using (var writer = new StreamWriter(new FileStream(string.Format("{0}{1}{2}", directory, "batch", FileExtension), FileMode.Append, FileAccess.Write, FileShare.Read), Encoding.ASCII))
    {
        Transform(document, xsltFileName, writer);
    writer.Close();
    }
    return null;
}
catch (IOException e)
{
    return e;
}
}

기본적으로 그 뒤에 아이디어는 몇 번 실행하려고 시도하고 문제가 지속되면 오류가 발생합니다.

문제를 해결합니다

다른 팁

한 가지만 원인이 될 수 있습니다. 다른 프로세스는 파일에 쓰는 것입니다. 다른 과정은 당신 자신 일 수도 있습니다.

해당 파일을 작성할 수있는 영역 주위에 시도/캐치 블록을 추가하는 것이 좋습니다. 캐치 블록에서 새 예외를 던져 전체 파일 경로를 추가하십시오.

var filePath = string.Format("{0}{1}{2}", directory, "batch", FileExtension);
try {
    using (var writer = new StreamWriter(filepath, true, Encoding.ASCII)) {
        Transform(...);
    }
}
catch (IOException ex) {
    throw new Exception(
        String.Format("Exception while transforming file {0}", filePath),
        ex);
}

Innerexception 및 Stack Trace를 포함하여 귀하가받은 완전한 예외를 게시하십시오.

또한 파일 사본이 Batch.csv에 쓸 수 있는지 확인하고 싶습니다.

당신이 기꺼이한다면, 다음과 같은 모드를 코드에 시도하는 것은 어떻습니까?

스트림 라이터 Param을 취하는 문서를 인쇄하는 과부하를 추가하십시오. 다음과 같이 Base.PrintDocuments를 수정하십시오.

using ( var writer = new StreamWriter ( string.Format ( "{0}{1}{2}", directory, "batch", FileExtension ), true, Encoding.ASCII ) )
{
    foreach ( var document in documents )
    {
        PrintDocument ( document, xsltFileName, directory, tempImageDirectory, writer );
    }
}

protected override void PrintDocument ( XmlDocument document, string xsltFileName, string directory, string tempImageDirectory, StreamWriter writer )
{
    if ( RemoveDiatrics )
    {
        var docXml = document.OuterXml;
        document = new XmlDocument ( );
        document.LoadXml ( docXml );
    }

   Transform ( document, xsltFileName, writer );        
}

이것이 실패한다면 ... 항상 비관론자 ... 나는 가능한 범인으로 변환을보고있을 것입니다. 그러나 나는 그것이 글을 쓰는 것 외에는 텍스트 작가와 아무것도하지 않는다는 것을 알고 있습니다. 어쨌든, 시간이 있다면 샷을주고 작가를 만들어 솔루션 (빠른 수정) 일 수 있습니다. 작동하는지 알려주십시오.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top