파일 IO 수행 시 예외를 올바르게 처리하는 방법
-
01-07-2019 - |
문제
종종 나는 어떤 방식으로든 파일과 상호 작용하는 것을 발견하지만 코드를 작성한 후에는 그것이 실제로 얼마나 거친 것인지 항상 확신하지 못합니다.문제는 파일 관련 작업이 어떻게 실패할 수 있는지, 따라서 기대치를 처리하는 가장 좋은 방법이 무엇인지 완전히 확신할 수 없다는 것입니다.
간단한 해결책은 코드에서 발생하는 IOException을 포착하고 사용자에게 "액세스할 수 없는 파일" 오류 메시지를 표시하는 것 같지만 좀 더 세분화된 오류 메시지를 얻는 것도 가능합니다.다른 프로그램에 의해 파일이 잠기는 오류와 하드웨어 오류로 인해 데이터를 읽을 수 없는 오류의 차이를 판단할 수 있는 방법이 있습니까?
다음 C# 코드가 주어지면 사용자 친화적인(최대한 유익한) 방식으로 오류를 어떻게 처리하시겠습니까?
public class IO
{
public List<string> ReadFile(string path)
{
FileInfo file = new FileInfo(path);
if (!file.Exists)
{
throw new FileNotFoundException();
}
StreamReader reader = file.OpenText();
List<string> text = new List<string>();
while (!reader.EndOfStream)
{
text.Add(reader.ReadLine());
}
reader.Close();
reader.Dispose();
return text;
}
public void WriteFile(List<string> text, string path)
{
FileInfo file = new FileInfo(path);
if (!file.Exists)
{
throw new FileNotFoundException();
}
StreamWriter writer = file.CreateText();
foreach(string line in text)
{
writer.WriteLine(line);
}
writer.Flush();
writer.Close();
writer.Dispose();
}
}
해결책
...하지만 좀 더 세분화된 오류 메시지를 얻을 수 있습니까?
예.가서 잡아라 IOException
, 그리고 Exception.ToString()
상대적으로 관련된 오류 메시지를 표시하는 방법입니다..NET Framework에서 생성된 예외는 이러한 유용한 문자열을 제공하지만 사용자 고유의 예외를 발생시키려면 해당 문자열을 Exception
의 생성자는 다음과 같습니다:
throw new FileNotFoundException("File not found");
또한, 절대적으로 다음과 같이 스콧 도먼, 그걸 사용해 using
성명.그런데 주목할 점은, using
진술은 실제로 그렇지 않습니다 catch
무엇이든 그래야 합니다.예를 들어, 파일이 존재하는지 확인하기 위한 테스트는 오히려 경쟁 조건을 유발할 수 있습니다. 짜증나는.거기에 넣어두는 것은 실제로 당신에게 어떤 유익도 주지 않습니다.이제 독자를 위해 다음을 제공합니다.
try {
using (StreamReader reader = file.OpenText()) {
// Your processing code here
}
} catch (IOException e) {
UI.AlertUserSomehow(e.ToString());
}
즉, 기본 파일 작업의 경우:
1.사용 using
2, using 문이나 함수를 try
/catch
저것 catch
예 IOException
삼.사용 Exception.ToString()
당신의 catch
유용한 오류 메시지를 얻으려면
4.예외 파일 문제를 직접 감지하려고 하지 마십시오..NET이 대신 처리해 드립니다.
다른 팁
가장 먼저 변경해야 할 것은 StreamWriter 및 StreamReader를 호출하여 다음과 같이 using 문으로 래핑하는 것입니다.
using (StreamReader reader = file.OpenText())
{
List<string> text = new List<string>();
while (!reader.EndOfStream)
{
text.Add(reader.ReadLine());
}
}
그러면 Close 및 Dispose 호출이 처리되고 실제로 try/finally 블록으로 래핑되므로 실제 컴파일된 코드는 다음과 같습니다.
StreamReader reader = file.OpenText();
try
{
List<string> text = new List<string>();
while (!reader.EndOfStream)
{
text.Add(reader.ReadLine());
}
}
finally
{
if (reader != null)
((IDisposable)reader).Dispose();
}
여기서 이점은 예외가 발생하더라도 스트림이 닫히도록 보장할 수 있다는 것입니다.
좀 더 명시적인 예외 처리에 관해서는 실제로 발생하려는 작업에 따라 다릅니다.귀하의 예에서는 파일이 존재하는지 명시적으로 테스트하고 사용자에게는 충분할 수 있지만 그렇지 않을 수도 있는 FileNotFoundException을 발생시킵니다.
- File.Exists()를 건너뜁니다.다른 곳에서 처리하거나 CreateText()/OpenText()가 발생시키도록 하세요.
- 최종 사용자는 일반적으로 성공 여부에만 관심을 갖습니다.실패하면 그냥 그렇게 말하세요. 그는 세부 사항을 원하지 않습니다.
.NET에서 실패한 내용과 이유에 대한 세부 정보를 얻을 수 있는 기본 제공 방법을 찾지 못했지만 CreateFile을 기본으로 사용하면 무엇이 잘못되었는지 알려줄 수 있는 수천 개의 오류 코드가 있습니다.
파일 존재 여부를 확인하고 메시지 없이 FileNotFoundException을 발생시키는 것이 의미가 없습니다.프레임워크는 메시지와 함께 FileNotFoundException 자체를 발생시킵니다.
예제의 또 다른 문제는 예외가 있는 경우에도 삭제 가능한 클래스가 적절하게 삭제되도록 하기 위해 try/finally 패턴이나 using 문을 사용해야 한다는 것입니다.
다음과 같이 이 작업을 수행하고 메서드 외부에서 예외를 포착하고 예외 메시지를 표시합니다.
public IList<string> ReadFile(string path)
{
List<string> text = new List<string>();
using(StreamReader reader = new StreamReader(path))
{
while (!reader.EndOfStream)
{
text.Add(reader.ReadLine());
}
}
return text;
}
파일 닫기를 단순화하기 위해 using 문을 사용하겠습니다.보다 MSDN C# 사용 문
MSDN에서:
using (TextWriter w = File.CreateText("log.txt")) {
w.WriteLine("This is line one");
w.WriteLine("This is line two");
}
using (TextReader r = File.OpenText("log.txt")) {
string s;
while ((s = r.ReadLine()) != null) {
Console.WriteLine(s);
}
}
아마도 이것은 당신이 찾고 있는 것이 아닐 수도 있지만, 예외 처리를 사용하는 종류를 다시 생각해 보십시오.적어도 프로그래머를 사용자로 생각하는 한 처음에는 예외 처리를 "사용자 친화적"으로 취급해서는 안 됩니다.
이에 대한 요약은 다음 기사일 수 있습니다. http://goit-postal.blogspot.com/2007/03/brief-introduction-to-Exception.html .
나는 파일을 확인하려고 노력할 것입니다. 읽기/쓰기를 호출하기 전에 존재하고 오류를 발생시키고 나중에 확인하는 오버헤드를 생성하는 대신 확인이 매우 쉽기 때문에 거기에 있는 사용자에게 응답합니다.오류 발생의 필요성을 이해하지만 특히 이 경우 간단한 확인이 더 나은 솔루션이 될 것입니다.내 말은 파일이 존재하는지 확인하는 방법을 하나 더 추가한다는 것입니다.
또한 파일이 종료되는지 미리 확인하면 파일에 쓸 수 없으면 다른 것이 파일을 차단하고 있다는 것을 알 수 있습니다.또한 여러 예외를 포착할 수 있으며, 일치하는 첫 번째 예외가 포착됩니다. 그러나 아마도 이것을 알고 있을 것입니다...