C# 在C语言中处理文件时如何正确处理异常#
我读过很多关于适当异常处理的博客/文章/书籍章节,但我仍然不清楚这个主题。我将试着用下面的例子来说明我的问题 考虑具有以下要求的类方法:C# 在C语言中处理文件时如何正确处理异常#,c#,.net,exception,exception-handling,C#,.net,Exception,Exception Handling,我读过很多关于适当异常处理的博客/文章/书籍章节,但我仍然不清楚这个主题。我将试着用下面的例子来说明我的问题 考虑具有以下要求的类方法: 接收文件路径列表作为参数 读取每个文件的文件内容,如果尝试执行此操作时出现任何问题,请跳过 返回表示文件内容的对象列表 所以规格很简单,下面是我如何开始编码的: 公共类文件内容 { 公共字符串文件路径{get;set;} 公共字节[]内容{get;set;} 公共文件内容(字符串文件路径,字节[]内容) { this.FilePath=FilePath; 这个
公共类文件内容
{
公共字符串文件路径{get;set;}
公共字节[]内容{get;set;}
公共文件内容(字符串文件路径,字节[]内容)
{
this.FilePath=FilePath;
这个。内容=内容;
}
}
静态列表GetFileContents(列表路径)
{
var resultList=新列表();
foreach(路径中的变量路径)
{
//打开“路径”指向的文件
//将文件读取到FileContent对象
//将文件内容添加到结果列表
//关闭文件
}
返回结果列表;
}
现在请注意2。根据规范,该方法应“跳过因某种原因无法读取内容的任何文件”。因此,发生这种情况可能有许多不同的原因(例如,文件不存在,由于缺乏安全权限而拒绝访问文件,文件被锁定并被其他应用程序使用等等),但问题是,我不应该在意原因是什么,我只想在可能的情况下读取文件的内容,或者在不存在的情况下跳过文件。我不在乎错误是什么
那么如何正确地实现这个方法呢
正确处理异常的第一条规则是永不捕获一般异常。那么这个代码就不好了:
静态列表GetFileContents(列表路径)
{
var resultList=新列表();
foreach(路径中的变量路径)
{
尝试
{
使用(FileStream-stream=File.Open(路径,FileMode.Open))
使用(BinaryReader=新的BinaryReader(流))
{
int fileLength=(int)stream.Length;
字节[]缓冲区=新字节[文件长度];
reader.Read(缓冲区,0,文件长度);
Add(新文件内容(路径、缓冲区));
}
}
捕获(例外情况除外)
{
//此文件无法读取,请不要执行任何操作…只需跳过该文件
}
}
返回结果列表;
}
正确异常处理的下一条规则是:只捕获您可以处理的特定异常。我不关心处理任何可能抛出的特定异常,我只想检查文件是否可以读取。我如何才能以适当的最佳实践方式做到这一点?我对这个问题的解决方案通常基于可能的例外情况的数量。如果只有几个,我为每个指定catch块。如果有很多可能,我会抓住所有的例外。强制开发人员总是捕获特定的异常可能会导致一些非常难看的代码。您的要求很明确-跳过无法读取的文件。那么,通用异常处理程序有什么问题呢?它允许您以一种简单、干净、可读、可扩展和可维护的方式执行任务 如果在将来的任何日期,您希望以不同的方式处理多个可能的异常,您可以在常规异常之上添加特定异常的捕获 那么您希望看到下面的代码?请注意,如果添加更多代码来处理文件读取,则必须将所有新异常添加到此列表中。这一切都是为了什么也不做
try
{
// find, open, read files
}
catch(FileNotFoundException) { }
catch(AccessViolation) { }
catch(...) { }
catch(...) { }
catch(...) { }
catch(...) { }
catch(...) { }
catch(...) { }
约定是一种指导原则,是创建好代码的好方法,但不要为了保持某种奇怪的礼仪而使代码过于复杂
对我来说,正确的礼仪是永远不要在浴室里说话。但是当老板在那里跟你打招呼时,你也会跟他打招呼。因此,如果您不想以不同的方式处理多个异常,则不需要捕获每个异常
编辑:所以我建议如下
try
{
// find, open, read files
}
catch { } // Ignore any and all exceptions
上面告诉我不要在意抛出哪个异常。通过不指定异常,甚至只指定System.exception,我允许.NET默认使用它。所以下面的代码是相同的
try
{
// find, open, read files
}
catch(Exception) { } // Ignore any and all exceptions
或者,如果您至少要记录它:
try
{
// find, open, read files
}
catch(Exception ex) { Logger.Log(ex); } // Log any and all exceptions
这种情况下你可以考虑的是,在<代码> FieloToFuntuxPosip>/Cuth>之间,因为它们太多,你不能捕捉到,并且最普通的<代码>异常< /代码>,仍然有层<代码> IOExabue/COD>。p>
一般来说,您将尝试捕获尽可能具体的异常,但特别是如果您捕获异常时没有实际使用它们抛出错误,那么您最好捕获一组异常。尽管如此,您仍将尽量使其具体化如果您在一种方法中混合了不同的操作,更改代码将使您的问题更容易回答:
static List<FileContent> GetFileContents(List<string> paths)
{
var resultList = new List<FileContent>();
foreach (var path in paths)
{
if (CanReadFile(path){
resultList.Add(new FileContent(path, buffer));
}
return resultList;
}
static bool CanReadFile(string Path){
try{
using (FileStream stream = File.Open(path, FileMode.Open))
using (BinaryReader reader = new BinaryReader(stream))
{
int fileLength = (int)stream.Length;
byte[] buffer = new byte[fileLength];
reader.Read(buffer, 0, fileLength);
}
}catch(Exception){ //I do not care what when wrong, error when reading from file
return false;
}
return true;
}
静态列表GetFileContents(列表路径)
{
var resultList=新列表();
foreach(路径中的变量路径)
{
if(CanReadFile(path){
Add(新文件内容(路径、缓冲区));
}
返回结果列表;
}
静态bool CanReadFile(字符串路径){
试一试{
使用(FileStream-stream=File.Open(路径,FileMode.Open))
使用(BinaryReader=新的BinaryReader(流))
{
int fileLength=(int)stream.Length;
字节[]缓冲区=新字节[文件长度];
reader.Read(缓冲区,0,文件长度);
}
}catch(Exception){//我不在乎什么时候出错,什么时候从文件中读取错误
返回false;
}
返回true;
}