简体   繁体   English

尝试在C#中捕获语句

[英]Try, catch statement in C#

I have the following C# code for calculating each file's hash in a certain, user specified directory. 我有以下C#代码,用于计算用户指定目录中每个文件的哈希值。 The point is that it works fine, until it encounters a file that it cannot access. 关键是,它会正常工作,直到遇到无法访问的文件为止。 When it finds something like this, it just throws an error message and exits the program. 当找到类似的东西时,它只会抛出一条错误消息并退出程序。 What I want it instead to do is, throw an error message with the name of the file that cannot be accessed, write that there is an error in accessing that file, and continue executing the program with the other files in the directory. 我想要它做的是,抛出一个错误消息,显示无法访问的文件的名称,写出访问该文件时出错,然后继续执行目录中其他文件的程序。 If someone can help me edit my code and achieve those things I would be glad. 如果有人可以帮助我编辑代码并实现这些目标,我将很高兴。

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

    }

Move your try/catch inside the foreach . 将您的try / catch foreach You haven't explained in your post, but I'm guessing that's where you encounter the exception. 您没有在帖子中进行解释,但是我猜这是您遇到异常的地方。

In doing so, any exception caused by the code in there will be caught and allow the loop to continue. 这样,将捕获由其中的代码引起的任何异常,并使循环继续进行。

Careful, though -- these two lines are still not exception-safe: 但是要小心-这两行仍然不是异常安全的:

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

You'll want to account for that as well. 您还要考虑到这一点。

If you want it to show what exactly what file/directory caused the issue, just toString the exception, for example: 如果要显示导致问题的确切文件/目录是什么,则只需将异常toString设为toString ,例如:

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

If toString doesn't give you the desired output, try ex.Message . 如果toString没有给您想要的输出,请尝试ex.Message I always just use toString though. 我总是只使用toString

EDIT credit to Ken Henderson 编辑致谢肯·亨德森

When using any kind of Stream , you should put it in a using block. 使用任何类型的Stream ,都应将其放在using块中。 The garbage collector will Close the stream eventually, but its good practice to do this, as a using block will close the stream as soon as you're done using it: 垃圾收集器最终将Close流,但是这样做的好习惯是, using完后, 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

You should reorganize your code like this: 您应该像这样重新组织代码:

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

Scope is the keyword here. 范围是此处的关键字。

Your try catch surrounds the entire foreach. 您的尝试抓住了整个森林。 This means that when there is an error, it will exit out of the foreach. 这意味着当出现错误时,它将退出foreach。 You want to have the try-catch closer to the point of origin (that being fInfo.Open(FileMode.Open) ). 您想要使try-catch靠近原点(即fInfo.Open(FileMode.Open) )。 That way, after an error it can just continue processing the loop. 这样,在发生错误后,它可以继续处理循环。

Try this instead: 尝试以下方法:

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


}

您还应该处理UnauthorizedAccessException ,如果无法访问文件,则抛出该异常。

Might be I'm overseeing something, because the solution is rather simple, but; 我可能正在监督某件事,因为解决方案很简单,但是;

place the Try-Catch block dealing with the access problems inside the for each - in case one file is not accessible, the exception is thrown, catched and after printing the error message the foreach is continued with the next file in the list. 将Try-Catch块放置在for每个文件的内部-如果无法访问一个文件,则引发,捕获异常,并在输出错误消息后,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.");
    }

}

To know which file is not accessible you could use the following snippet : 要了解无法访问哪个文件,可以使用以下代码段:

catch(FileNotFoundException ex)
{
Console.writeLine("File not found " + ex.FileName);
}

handle UnauthorizedAccessException and put try statement in foreach statement. 处理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;
    }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM