C# 錯誤/例外處理 (Exception)

下面是一個很簡單的程式碼,用途就是把 test.txt 檔案中的所有內容讀取出來,放到 text 變數中:
    
var text = File.ReadAllText($"test.txt");
    

但是一執行就發生錯誤:
    
Unhandled exception. System.IO.FileNotFoundException: Could not find file 'C:\Users\ruyut\RiderProjects\2024\test\ConsoleAppExceptionTest0823\ConsoleAppExceptionTest0823\bin\Debug\net8.0\test.txt'.
File name: 'C:\Users\ruyut\RiderProjects\2024\test\ConsoleAppExceptionTest0823\ConsoleAppExceptionTest0823\bin\Debug\net8.0\test.txt'
   at Microsoft.Win32.SafeHandles.SafeFileHandle.CreateFile(String fullPath, FileMode mode, FileAccess access, FileShare share, FileOptions options)
   at Microsoft.Win32.SafeHandles.SafeFileHandle.Open(String fullPath, FileMode mode, FileAccess access, FileShare share, FileOptions options, Int64 preallocationSize, Nullable`1 unixCreateMode)
   at System.IO.Strategies.OSFileStreamStrategy..ctor(String path, FileMode mode, FileAccess access, FileShare share, FileOptions options, Int64 preallocationSize, Nullable`1 unixCreateMode)
   at System.IO.Strategies.FileStreamHelpers.ChooseStrategyCore(String path, FileMode mode, FileAccess access, FileShare share, FileOptions options, Int64 preallocationSize, Nullable`1 unixCreateMode)
   at System.IO.StreamReader.ValidateArgsAndOpenPath(String path, Encoding encoding, Int32 bufferSize)
   at System.IO.File.ReadAllText(String path, Encoding encoding)
   at ConsoleAppExceptionTest0823.Program.Main(String[] args) in C:\Users\ruyut\RiderProjects\2024\test\ConsoleAppExceptionTest0823\ConsoleAppExceptionTest0823\Program.cs:line 8

Process finished with exit code -532,462,766.
    

其實不能說是錯誤,而是發生了程式無法處理的例外(Exception)情況,上面拋出的例外是 System.IO.FileNotFoundException ,代表找不到指定的檔案。

如果有仔細看程式碼,會發現在 File.ReadAllText 這個方法的說明中就有標記可能會拋出的例外,其中就有包含本次遇到的 FileNotFoundException 例外。

該如何避免遇到例外情況呢?我們可以在執行前先檢查所有條件是否都符合,例如上面的範例就是在讀取檔案前先檢查檔案是否存在,如果檔案不存在就顯示訊息並終止程式,就可以避免在 File.ReadAllText 方法中遇到檔案不存在的例外了。
    
        if (!File.Exists("test.txt"))
        {
            Console.WriteLine("File not found");
            return;
        }

        var text = File.ReadAllText($"test.txt");
    

但是在程式的執行中一定會遇到例外,如果我們不做處理,程式很可能就會卡住或是死在這裡,這時候我們就可以使用 try catch 區塊來捕捉例外:
    
        try
        {
            var text = File.ReadAllText($"test.txt");
        }
        catch (Exception e) // 捕捉全部例外
        {
            Console.WriteLine($"遇到例外情況: {e.Message}");
            // 遇到例外情況: Could not find file 'test.txt'.
        }
    

也可以只捕捉指定的例外情況:
    
        try
        {
            var text = File.ReadAllText($"test.txt");
        }
        catch (System.IO.FileNotFoundException e) // 只捕捉 FileNotFoundException 例外
        {
            Console.WriteLine($"找不到檔案: {e.Message}");
            // 找不到檔案: Could not find file 'test.txt'.
        }
    

我們在捕捉錯誤後還可以使用 throw 關鍵字,把原本的例外再拋出一次,這樣做的好處是在遇到例外的時候有一定的緩衝,最常見的就是在這之中留下日誌紀錄(log)方便日後除錯,然後交由上層再去處理例外
    
        try
        {
            var text = File.ReadAllText($"test.txt");
        }
        catch (System.IO.FileNotFoundException e)
        {
            Console.WriteLine($"找不到檔案: {e.Message}");
            throw; // 重新拋出例外
        }
    



參考資料:
Microsoft.Learn - Exception Handling (C# Programming Guide)
Microsoft.Learn - How to handle an exception using try/catch
Microsoft.Learn - Exception-handling statements - throw, try-catch, try-finally, and try-catch-finally

留言

張貼留言

如果有任何問題、建議、想說的話或文章題目推薦,都歡迎留言或來信: a@ruyut.com