【问题标题】:File.Create and File.OpenWrite does not release the file even if it's closed and also disposedFile.Create 和 File.OpenWrite 不会释放文件,即使它已关闭并且也已处置
【发布时间】:2019-10-17 19:49:16
【问题描述】:

我正在使用 HttpWebRequest 对象下载 pdf 文件,并在复制数据后立即使用所有“使用”块以及 .Close 方法将内容从响应流直接写入 FileStream。 下一步,我需要使用一些 3rd 方库 (iText7) 从该 pdf 文件中提取一些文本,但它无法访问该文件。 起初,我认为这是与 iText7 相关的问题,但后来我意识到似乎并非如此,因为我什至无法从文件资源管理器中删除文件,我自己的应用程序出现“文件正在使用”错误。

示例代码如下:

            HttpWebRequest webReq = (HttpWebRequest)HttpWebRequest.Create(url);
            webReq.AllowAutoRedirect = true;
            webReq.CookieContainer = Cookies;
            webReq.UserAgent = UserAgent;
            webReq.Referer = Referrer;
            webReq.Method = WebRequestMethods.Http.Get;

            using (HttpWebResponse response = (HttpWebResponse)webReq.GetResponse())
            {
                using (Stream httpResponseStream = response.GetResponseStream())
                {
                    using (FileStream output = File.Create(file1))
                    {
                        httpResponseStream.CopyTo(output);
                        output.Close();
                    }
                    httpResponseStream.Close();
                    response.Close();

                    Cookies = webReq.CookieContainer;
                }
            }

            GC.Collect();

            ExtractPDFDoc(file1);//error throws in this function and the exception.message is "Cannot open document."

            Console.WriteLine("now waiting to let you check the file is in use? try delete it manually...");
            Console.ReadKey(); //added this line to ensure that file is actually in use. I can't even delete the file manually from windows file explorer at this time. But, interestingly, Acrobat Reader can OPEN the file when I double click, which makes me thing that Adobe and iText7 uses different methods to open the pdf file - but anyway - I can't help it tho.

你能帮忙看看这里出了什么问题吗?

对于那些想要查看 ExtractPDFDoc() 方法的人:

public static object ExtractPDFDoc(string filename)
    {

        iText.Kernel.Pdf.PdfReader pdfReader = null;
        iText.Kernel.Pdf.PdfDocument pdfDocument = null;


        try
        {

            pdfReader = new iText.Kernel.Pdf.PdfReader(filename);

            pdfDocument = new iText.Kernel.Pdf.PdfDocument(pdfReader);

        }
        catch (Exception ex)
        {

            pdfReader = null;
            pdfDocument = null;

            return new Exception(string.Format("ExtractPDFDoc() failed on file '{0}' with message '{1}'", filename, ex.Message));

            //this is where I get the error, ex.Message is 'Cannot open document.'
            //however, I can open it in Adobe Reader but I can't delete it before closing my app.
        }
}

【问题讨论】:

  • 你为什么要强制垃圾收集器行动?你几乎不必这样做。我怀疑这会导致意想不到的问题。
  • 不,我后来添加了它我得到了错误 - 只是尝试但没有帮助。错误在我添加之前就已经存在了。
  • 如果您使用 (...),则不应调用 obj.Close()。另外,您是否有完整的异常消息和/或回溯?
  • @LampToast 感谢您的建议,我禁用了所有 .Close() 方法,但它仍然是一样的......
  • 如果在使用 iText 打开文件之前设置断点怎么办?当调试器暂停时,您可以在 Windows 资源管理器中操作文件(重命名、移动等)吗?

标签: c# file stream


【解决方案1】:

如果我没记错的话,iText 对象都是 IDisposable 的,所以你也应该确保将它们处理掉。另外,我不知道您为什么要返回异常而不是抛出异常。

public static object ExtractPDFDoc(string filename)
{
    iText.Kernel.Pdf.PdfReader pdfReader = null;
    iText.Kernel.Pdf.PdfDocument pdfDocument = null;

    try
    {
        pdfReader = new iText.Kernel.Pdf.PdfReader(filename);
        pdfDocument = new iText.Kernel.Pdf.PdfDocument(pdfReader);
    }
    catch (Exception ex)
    {
        throw new Exception(string.Format("ExtractPDFDoc() failed on file '{0}' with message '{1}'", filename, ex.Message), ex);
    }
    finally
    {
        pdfReader?.Dispose();
        pdfDocument?.Dispose();
    }
}

与此无关,您还可以堆叠您的 using 语句而不是嵌套它们。

using (HttpWebResponse response = (HttpWebResponse)webReq.GetResponse())
using (Stream httpResponseStream = response.GetResponseStream())
using (FileStream output = File.Create(file1))
{
     // do stuff
}

【讨论】:

  • 我之前检查过,它们不是 IDisposable 但它们支持 pdfReader?.Close()pdfDocument?.Close() 方法...谢谢。
【解决方案2】:

非常抱歉,感谢@howcheng,我意识到是 iText7 在无法打开文档后使文件保持打开状态,因为输出文件夹中缺少它的一个依赖文件。

很明显,我应该在异常情况下对 iText7 对象执行.Close(),以避免这样的错误看法。

感谢您的所有帮助。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多