【问题标题】:Extract the filename from an IOException message从 IOException 消息中提取文件名
【发布时间】:2021-10-28 22:58:48
【问题描述】:

我想知道如何从 IOException 消息中提取文件路径。

以下代码搜索C:\Temp 下的子目录并检测是否有任何*_test.xlsx 正在打开:

class Program
{
    static void Main(string[] args)
    {
        string[] files = Directory.GetFiles(@"C:\Temp", "*_test.xlsx", SearchOption.AllDirectories);

        try 
        {
            if (files == null)
            {
                Console.WriteLine("File Not Found");
            }
            else
            {
                foreach (var file in files)
                {
                    using (Stream stream = new FileStream(file, FileMode.Open))
                    {
                        // Do Nothing
                    }
                }
            }
        }
        catch (IOException ex)
        {
            Console.WriteLine(ex); // Here I'd like to show only the 'C:\Temp\3_folder\3_test.xlsx' part
        }
    }
}

如果文件正在打开,则会捕获 IOException 并显示:

System.IO.IOException: The process cannot access the file 'C:\Temp\3_folder\3_test.xlsx' because it is being used by another process.
   at System.IO.FileStream.ValidateFileHandle(SafeFileHandle fileHandle)
   at System.IO.FileStream.CreateFileOpenHandle(FileMode mode, FileShare share, FileOptions options)
   at System.IO.FileStream..ctor(String path, FileMode mode, FileAccess access, FileShare share, Int32 bufferSize, FileOptions options)
   at System.IO.FileStream..ctor(String path, FileMode mode)
   at CheckIfFileInUse.Program.Main(String[] args) in C:\Users\xxxxx\source\repos\CheckIfFileInUse\Program.cs:line 22

但是,我不需要完整的消息。
我只需要文件路径(在本例中为C:\Temp\3_folder\3_test.xlsx)。

我搜索并找到了this answer,但这不是我想要的。
StackTrace() 的frame.GetFileName() 返回程序文件路径(在我的情况下为C:\Users\xxxxx\source\repos\CheckIfFileInUse\Program.cs)。

如何从 IOException 消息中提取文件路径?

【问题讨论】:

  • 一般来说:你不能,因为不是每个 IOException 都有与之关联的文件名。也许 EnofOfStreamException(这是一个 IOException)在不需要文件的 MemoryStream 上运行。
  • 不清楚为什么你不能自己跟踪这个?
  • Can't you test for System.IO.IOException: The process cannot access the file ' ?
  • 在这种情况下,我认为无论如何您都需要将 try/catch 向内移动,因此一个文件失败不会阻止其余文件的处理。 那么你已经知道哪个文件失败了。
  • @IanHacker 看到他的回答。不过,请考虑您想对迭代列表中的其余文件做什么。

标签: c# message filepath ioexception


【解决方案1】:

一般来说:你不能,因为不是每个 IOException 都有与之关联的文件名。也许 EndOfStreamException(这是一个 IOException)在不需要文件的 MemoryStream 上运行。

但是自己构建它是微不足道的。在内部级别捕获异常并抛出您自己的异常。请注意<-- 在哪里进行更改

class Program
{
    static void Main(string[] args)
    {
        string[] files = Directory.GetFiles(@"C:\Temp", "*_test.xlsx", SearchOption.AllDirectories);

        try 
        {
            if (files == null)
            {
                Console.WriteLine("File Not Found");
            }
            else
            {
                foreach (var file in files)
                {
                    try       // <--
                    {        
                        using (Stream stream = new FileStream(file, FileMode.Open))
                        {
                            // Do Nothing
                        }
                    }
                    catch (IOException ex)    // <--
                    {
                        var fileex = new IOExceptionWithFileInfo(file);
                        fileex.InnerException = ex; // Keep the original information
                        throw fileex;
                    }
                }
            }
        }
        catch (IOExceptionWithFileInfo ex)   // <--
        {
            Console.WriteLine(ex.FileName); 
        }
    }
}

作为练习的 OP 的 TODO:实现类 IOExceptionWithFileInfo,派生自 Exception。

在内部级别进行捕获还可以帮助您处理所有文件并构建所有有问题的文件的列表,如下所示:

var listOfErrors = new List<IOExceptionWithFileInfo>();
[...]
    catch (IOException ex)
    {
        var fileex = new IOExceptionWithFileInfo(file);
        fileex.InnerException = ex; // Keep the original information
        listOfErrors.Add(fileex);
    }
[...]
if (listOfErrors.Length > 0)
{
    // Display all of them to the user
}

【讨论】:

  • 我建议 OP 在重新抛出时将捕获的IOException 包含为InnerException。
  • 注意:这将丢弃列表中在失败后要迭代的所有文件的过程。
  • @Fildor:是的,就像原来的实现一样
  • @Llama:是的,我应该这样做。固定
  • @Fildor:也为此添加了一个解决方案,只是为了好玩。
猜你喜欢
  • 2018-10-18
  • 2012-07-23
  • 1970-01-01
  • 2012-05-04
  • 1970-01-01
  • 2014-07-22
  • 2020-10-17
  • 1970-01-01
  • 2016-03-26
相关资源
最近更新 更多