2010-10-19 38 views
6

Tôi phân tích cú pháp một tệp có dữ liệu bị MalFormed theo thời gian.Ngoại lệ khi ăn

và nó ném một ngoại lệ,

tôi muốn khôi phục từ ngoại lệ và bỏ qua dữ liệu bị định dạng sai.

Cách tốt nhất để làm điều này là gì?

try{ 
// parse file 
}catch(Exception){ 
//eat it. 
} 

* EDIT: * Tôi nghĩ, câu hỏi wasnt tôi hiểu rõ. tôi muốn phục hồi từ trường hợp ngoại lệ, bất kỳ ngoại lệ cho vấn đề đó, tôi không muốn chương trình của tôi dừng lại. nhưng để tiếp tục.

+11

Bắt ngoại lệ chung là một ý tưởng tồi. Bạn chỉ nên nắm bắt các ngoại lệ cụ thể mà bạn có thể xử lý. Điều này đã được nâng lên nhiều lần trên Stack Overflow. – ChrisF

+0

Bạn có muốn bỏ qua tất cả dữ liệu từ phân tích cú pháp hiện tại hay chỉ các dòng/yếu tố/ký tự xấu? – hemp

+4

Và ở đây tôi nghĩ rằng điều này sẽ là về việc ăn uống với thực phẩm Trung Quốc từ pizza pepperoni bình thường. (Có xấu khi các nhân viên phân phối biết tên của bạn, bạn làm gì và một chút về các dự án bạn đang làm việc?) – Brad

Trả lời

5

Tôi nghĩ rằng những gì bạn đang yêu cầu này là:

Khi phân tích một dòng tập tin bằng cách dòng, dữ liệu đôi khi dòng hiện tại đã bị thay đổi mà gây ra một ngoại lệ được ném vào mã của bạn. Có lẽ bạn chỉ cần cấu trúc mã của bạn sao cho try/catch chỉ bao quanh mã phân tích cú pháp, chứ không phải mã đọc dòng. Ví dụ:

using System; 
using System.IO; 
using System.Windows.Forms; 

public void ParseFile(string filepath) 
{ 
    TextReader reader = null; 

    try 
    { 
     reader = new StreamReader(filepath); 

     string line = reader.ReadLine(); 
     while (!string.IsNullOrEmpty(line)) 
     { 
      try 
      { 
       // parse line here; if line is malformed, 
       // general exception will be caught and ignored 
       // and we move on to the next line 
      } 
      catch (Exception) 
      { 
       // recommended to at least log the malformed 
       // line at this point 
      } 

      line = reader.ReadLine(); 
     } 
    } 
    catch (Exception ex) 
    { 
     throw new Exception("Exception when trying to open or parse file", ex); 
    } 
    finally 
    { 
     if (reader != null) 
     { 
      reader.Close(); 
      reader.Dispose(); 
     } 
     reader = null; 
    } 
} 

Khối try/catch bên ngoài là xử lý đóng đối tượng người đọc đúng cách nếu xảy ra sự cố khi mở hoặc đọc tệp. Khối try/catch bên trong là nuốt các ngoại lệ nếu dữ liệu đọc không đúng định dạng và không thể phân tích cú pháp chính xác.

Tôi đồng ý với khá nhiều người khác. Chỉ cần nuốt ngoại lệ có thể không tốt. Ít nhất, tôi khuyên bạn nên đăng nhập nó ở đâu đó.

+1

Trong phần đánh bắt bên ngoài, bạn sẽ muốn sử dụng 'throw;' thay vì gói ngoại lệ ban đầu trong một cái mới, để bảo vệ ngăn xếp cuộc gọi. Hơn nữa, nếu bạn sử dụng 'using (reader = new StreamReader (filepath))' thì bạn không cần khối ngoại lệ ngoài đó. – hemp

+0

@hemp Điều đáng nói đến là 'ném', sẽ không phải lúc nào cũng giữ nguyên ngăn xếp cuộc gọi và 'ném cũ', thậm chí còn ít hơn. Xem: https://weblogs.asp.net/fmarguerie/rethrowing-exceptions-and-preserving-the-full-call-stack-trace – Dan

+0

Bạn đúng @Dan, trong trường hợp ngoại lệ bị ném, bị bắt, và được rethrown trong cùng một chức năng, theo dõi stack sẽ chỉ hiển thị thông tin về nơi nó được rethrown. Trong thực tế đó là một trường hợp hiếm hoi. – hemp

0
try{ 
    // parse file 
    } 
    catch(Exception){ 
    //eat it. 
    } 
    finally 
    { 
     //cleanup must ... release system resources here (e.g. stream.Close() etc) 
     // code here always executes...even if the exception is unhandled 

    } 

// code will resume execution from this point onwards... 
0

đó làm việc - có thể bạn có thể đăng nhập các lỗi dù quá trong trường hợp bạn muốn xem những gì các dữ liệu đã gây ra ngoại lệ xảy ra và sử dụng để cải thiện luận phân tích của bạn.

4

Tóm lại, có thể bạn không nên sử dụng ngoại lệ cho việc này. Một cái gì đó giống như một TryParse mà trả về false là hiệu quả hơn nhiều và dễ dàng hơn để phục hồi. Xử lý ngoại lệ là một chút của phương pháp tiếp cận đối tượng cùn.

MSDN Guidance on Exception Handling

+2

TryParse chỉ phù hợp nếu bạn đang đọc một số kiểu nguyên thủy cung cấp các phương thức TryParse. "TryParse" không có ngoại lệ là không thể nếu bạn phân tích cú pháp từ luồng tệp và tệp đó bị thiếu - bạn sẽ cần xử lý ngoại lệ * ở đâu đó * để xử lý FileNotFoundException. –

+0

@ Jason, tôi nghĩ bạn đang hái trứng. Một phương pháp TryParse có sẵn bất cứ lúc nào bạn viết một. Nếu bạn chưa bao giờ viết, bạn có thể làm sai. MSDN gọi nó là ["Tester-Doer" pattern] (http://msdn.microsoft.com/en-us/library/ms229009.aspx) và khuyến khích nó như là một thực hành ưa thích (hơn xử lý các ngoại lệ). Không mở tệp để phân tích cú pháp; thay vào đó, trước tiên hãy kiểm tra xem nó có tồn tại không, sau đó thử mở nó để đọc, sau đó thử phân tích cú pháp luồng mở. Nếu bạn làm theo mẫu đó, không cần có FileNotFoundException, trừ khi bạn quyết định ném nó. – hemp

+1

@hemp: Nếu bạn kiểm tra xem tệp có tồn tại không, sau đó thử mở tệp để đọc, bạn sẽ nhận được ngoại lệ FileNotFound khi một luồng khác hoặc quá trình khác xóa tệp giữa cuộc gọi IsExists() của bạn và thực sự mở tệp. Không có vấn đề làm thế nào hiếm này là, mã của bạn là thiếu sót, trừ khi bạn đối phó với ngoại lệ có thể. Vấn đề là bạn * không thể * luôn tránh xử lý ngoại lệ (nhiều như tôi thích). Có, bạn có thể viết một phương pháp TryParse, nhưng để viết nó một cách chính xác, bạn gần như chắc chắn sẽ phải bao gồm một số xử lý ngoại lệ bên trong nó - bạn chỉ cần di chuyển trang web của catch {}. –

2

Có một số thông tin nền tảng tốt ở đây: Is there any valid reason to ever ignore a caught exception

Câu trả lời ngắn: trường hợp ngoại lệ là đắt tiền để sử dụng theo cách này. Nếu có thể, hãy kiểm tra đầu vào trước khi gửi nó để xử lý và làm bạn bỏ qua ở đó thay vì bỏ qua các ngoại lệ.

Cũng đảm bảo rằng bạn không đúc quá rộng mạng và ăn các trường hợp ngoại lệ hợp pháp mà bạn có thể muốn biết.

3

Nói chung, một cái gì đó như thế này:

try 
{ 
    // parse file 
} 
catch (FormatException) 
{ 
    // handle the exception 
} 
finally 
{ 
    // this block is always executed 
} 

Bạn nên tránh bắt chung Exception trường hợp và thay vào đó bắt một ngoại lệ đặc biệt, bất cứ điều gì mà bạn có thể.

1

Bắt ngoại lệ chung là một ý tưởng tồi nếu bạn mong đợi nó chỉ ném một hoặc hai loại ngoại lệ cụ thể cho các lỗi phân tích cú pháp cụ thể. Thường là tốt hơn để nắm bắt từng loại ngoại lệ cụ thể và xử lý độc lập để mã của bạn sẽ không chặn bất kỳ lỗi nào khác (có thể không mong muốn) (ví dụ: nếu tệp bị thiếu hoặc kết nối mạng hết giờ, nó sẽ được xử lý trong giống như cách tệp chứa dữ liệu bị hỏng?)

Tuy nhiên, bắt một ngoại lệ chung là một ý tưởng tuyệt vời nếu bạn cố tình cần/muốn nắm bắt tất cả các lỗi có thể và tiếp tục một cách duyên dáng. Điều này có thể xảy ra nếu việc xử lý tất cả các loại lỗi giống nhau (ví dụ: "nếu, vì bất kỳ lý do gì, tôi không thể đọc giá trị tùy chọn này, tôi sẽ trả về giá trị mặc định là 5" - điều đó tốt hơn rất nhiều so với chương trình của bạn. t nhận ra nó có thể ném một ngoại lệ do một thời gian chờ mạng). Nếu sử dụng một cách khôn ngoan, cách tiếp cận này có thể làm cho chương trình của bạn bằng chứng đạn - nhưng nếu sử dụng không chính xác bạn có thể ngăn chặn các lỗi mà bạn cần phải biết và sửa chữa, và điều này có thể rất đau đớn.

Khi loại bỏ bất kỳ ngoại lệ nào, bạn nên luôn xem xét cẩn thận báo cáo lỗi - bạn có nên cho người dùng biết rằng bạn đã gặp sự cố không? Nếu bạn đăng nhập nó trong một tập tin dấu vết để khi một khách hàng phàn nàn về một cái gì đó không hoạt động đúng, bạn có thể theo dõi trở lại nguồn gốc của vấn đề? Hoặc bạn nên âm thầm bỏ qua nó?Chỉ cần cẩn thận vì sự kìm hãm quá nhiệt tình có thể khiến cho rất khó để tìm ra lý do tại sao một progam hoạt động không thể đoán trước được.

0

Tôi có cảm giác rằng bạn thấy những thứ như màu đen & màu trắng, và điều đó không cảm thấy đúng .. Có, hầu hết các lần, không tốt để nắm bắt mọi thứ và cẩu thả khi nói đến xác thực đầu vào, nhưng không phải lúc nào. Điều này rất có thể là một trường hợp đặc biệt. Tôi không biết gì về loại tệp sẽ được phân tích cú pháp, nhưng ngoại lệ có thể là điều đúng.

Trước khi chúng tôi quyết định những gì là tốt nhất, cung cấp cho chúng tôi biết thêm chi tiết :)

Các vấn đề liên quan