0

我有以下 C# 代码用于计算某个用户指定目录中每个文件的哈希值。关键是它可以正常工作,直到遇到无法访问的文件。当它发现这样的东西时,它只是抛出一条错误消息并退出程序。我想要它做的是,抛出一条带有无法访问的文件名的错误消息,写下访问该文件时出错,然后继续使用目录中的其他文件执行程序。如果有人可以帮助我编辑我的代码并实现这些目标,我会很高兴。

    private void SHA256Directory(string directory)
    {
        try
        {
            SHA256 DirectorySHA256 = SHA256Managed.Create();
            byte[] hashValue;

            DirectoryInfo dir = new DirectoryInfo(directory);
            FileInfo[] files = dir.GetFiles();

            foreach (FileInfo fInfo in files)
            {
                FileStream fStream = fInfo.Open(FileMode.Open);
                fStream.Position = 0;
                hashValue = DirectorySHA256.ComputeHash(fStream);

                Console.WriteLine(fInfo.Name);
                Miscellaneous.ByteArrayToHex(hashValue);
                Miscellaneous.ByteArrayToBase64(hashValue);
                Console.WriteLine();

                fStream.Close();
            }

            return;
        }
        catch(DirectoryNotFoundException)
        {
            Console.WriteLine("Error: The directory specified could not be found.");
        }
        catch(IOException)
        {
            Console.WriteLine("Error: A file in the directory could not be accessed.");
        }
        catch(ArgumentNullException)
        {
            Console.WriteLine("Error: The argument cannot be null or empty.");
        }

    }
4

8 回答 8

8

将您的 try/catch 移动到foreach. 你没有在你的帖子中解释,但我猜这就是你遇到异常的地方。

这样一来,由其中的代码引起的任何异常都将被捕获并允许循环继续。

不过要小心——这两行仍然不是异常安全的:

DirectoryInfo dir = new DirectoryInfo(directory);
FileInfo[] files = dir.GetFiles();

您也需要考虑这一点。

如果您希望它显示究竟是什么文件/目录导致了问题,只是toString例外,例如:

catch(DirectoryNotFoundException ex)
{
    Console.WriteLine("Error: The directory specified could not be found: " + ex.toString());
}

如果toString没有为您提供所需的输出,请尝试ex.Message. 不过我总是只用toString

编辑信贷肯亨德森

使用任何类型的 时Stream,都应将其放在一个using块中。垃圾收集器Close最终会处理流,但这样做是一种很好的做法,因为一个using块会在您使用完流后立即关闭它:

using (FileStream fStream = fInfo.Open(FileMode.Open)) 
{
    fStream.Position = 0;
    hashValue = DirectorySHA256.ComputeHash(fStream);

    Console.WriteLine(fInfo.Name);
    Miscellaneous.ByteArrayToHex(hashValue);
    Miscellaneous.ByteArrayToBase64(hashValue);
    Console.WriteLine();
} // No need for fStream.Close() any more, the using block will take care of it for you
于 2013-05-02T13:08:58.903 回答
2

您应该像这样重新组织您的代码:

private void SHA256Directory(string directory)
{
    try
    {
        DirectoryInfo dir = new DirectoryInfo(directory);
        FileInfo[] files = dir.GetFiles();

        foreach (FileInfo fInfo in files)
        {
            try
            {
                SHA256 DirectorySHA256 = SHA256Managed.Create();
                byte[] hashValue;

                FileStream fStream = fInfo.Open(FileMode.Open);
                fStream.Position = 0;
                hashValue = DirectorySHA256.ComputeHash(fStream);

                Console.WriteLine(fInfo.Name);
                Miscellaneous.ByteArrayToHex(hashValue);
                Miscellaneous.ByteArrayToBase64(hashValue);
                Console.WriteLine();

                fStream.Close();
            }
            catch (...)
            {
                // Handle other exceptions here. Through finfo, you can
                // access the file name
            }
        }
    }
    catch (...)
    {
        // Handle directory/file iteration exceptions here
    }
}
于 2013-05-02T13:11:12.350 回答
1

范围是这里的关键字。

您的 try catch 围绕整个 foreach。这意味着当出现错误时,它将退出foreach。您想让 try-catch 更接近原点(即fInfo.Open(FileMode.Open))。这样,在出错后它可以继续处理循环。

于 2013-05-02T13:10:38.793 回答
1

试试这个:

private void SHA256Directory(string directory)
{
    SHA256 DirectorySHA256 = SHA256Managed.Create();
    byte[] hashValue;

    DirectoryInfo dir = new DirectoryInfo(directory);
    FileInfo[] files = dir.GetFiles();

    foreach (FileInfo fInfo in files)
    {
        try
        {
            FileStream fStream = fInfo.Open(FileMode.Open);
            fStream.Position = 0;
            hashValue = DirectorySHA256.ComputeHash(fStream);

            Console.WriteLine(fInfo.Name);
            Miscellaneous.ByteArrayToHex(hashValue);
            Miscellaneous.ByteArrayToBase64(hashValue);
            Console.WriteLine();

            fStream.Close();
        }
        catch(DirectoryNotFoundException)
        {
            Console.WriteLine("Error: The directory specified could not be found.");
        }
        catch(IOException)
        {
            Console.WriteLine("Error: A file in the directory could not be accessed.");
        }
        catch(ArgumentNullException)
        {
            Console.WriteLine("Error: The argument cannot be null or empty.");
        }
    }
    return;
}


}
于 2013-05-02T13:10:56.410 回答
0

要知道哪个文件不可访问,您可以使用以下代码段:

catch(FileNotFoundException ex)
{
Console.writeLine("File not found " + ex.FileName);
}
于 2013-05-02T13:12:53.000 回答
0

UnauthorizedAccessException如果文件不可访问,您还应该处理抛出的问题。

于 2013-05-02T13:12:06.217 回答
0

处理 UnauthorizedAccessException 并将 try 语句放在 foreach 语句中。

private  void SHA256Directory(string directory)
    {
        SHA256 DirectorySHA256 = SHA256Managed.Create();
        byte[] hashValue;

        DirectoryInfo dir = new DirectoryInfo(directory);
        FileInfo[] files = dir.GetFiles();

        foreach (FileInfo fInfo in files)
        {
            try
            {
                FileStream fStream = fInfo.Open(FileMode.Open);
                fStream.Position = 0;
                hashValue = DirectorySHA256.ComputeHash(fStream);

                Console.WriteLine(fInfo.Name);
                Miscellaneous.ByteArrayToHex(hashValue);
                Miscellaneous.ByteArrayToBase64(hashValue);
                Console.WriteLine();

                fStream.Close();
            }
            catch (DirectoryNotFoundException)
            {
                Console.WriteLine("Error: The directory specified could not be found.");
            }
            catch (UnauthorizedAccessException)
            {
                Console.WriteLine("Error: A file in the directory could not be accessed.in {0}", fInfo.Name);
            }
            catch (ArgumentNullException)
            {
                Console.WriteLine("Error: The argument cannot be null or empty.");
            }
            catch (IOException)
            {
                Console.WriteLine("Error:IOExcepiton occured");
            }

        }

        return;
    }
于 2013-05-02T13:17:46.537 回答
0

可能是我正在监督某些事情,因为解决方案相当简单,但是;

将处理访问问题的 Try-Catch 块放置在 for each 中 - 如果一个文件不可访问,则会引发、捕获异常,并在打印错误消息后 foreach 继续处理列表中的下一个文件。

private void SHA256Directory(string directory)
{
    try
    {
        SHA256 DirectorySHA256 = SHA256Managed.Create();
        byte[] hashValue;

        DirectoryInfo dir = new DirectoryInfo(directory);
        FileInfo[] files = dir.GetFiles();

        foreach (FileInfo fInfo in files)
        {
           try
           {


               FileStream fStream = fInfo.Open(FileMode.Open);
               fStream.Position = 0;
               hashValue = DirectorySHA256.ComputeHash(fStream);

               Console.WriteLine(fInfo.Name);
               Miscellaneous.ByteArrayToHex(hashValue);
               Miscellaneous.ByteArrayToBase64(hashValue);
               Console.WriteLine();

               fStream.Close();
            }
            catch(IOException)
            {
               Console.WriteLine("Error: A file in the directory could not be accessed.");
            }
        }

        return;
    }
    catch(DirectoryNotFoundException)
    {
        Console.WriteLine("Error: The directory specified could not be found.");
    }
    catch(ArgumentNullException)
    {
        Console.WriteLine("Error: The argument cannot be null or empty.");
    }

}
于 2013-05-02T13:12:23.277 回答