2010-10-19 26 views
6

Zaman zaman MalFormed verisine sahip bir dosyayı ayrıştırarak ayırıyorum. İstisnaları Yemek Etme

ve istisna atan s

i kötü biçimlendirilmiş verileri özel kurtarmak ve görmezden istiyorum

.

Bunu yapmanın en iyi yolu ne?

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

* DÜZENLEME: Bence *, sorum degildi iyi anladım. İstisnadan kurtarmak istiyorum, bu konuyla ilgili herhangi bir istisna, programımın durmasını istemiyorum. ama devam etmek. Çok durumunda veri istisna olur ve ayrıştırma mantığını geliştirmek için bu kullanmak neden olduğunu ne olduğunu görmek istedim ama belki hataları günlüğe olabilir - çalışır

+11

Genel kural dışı durumu yakalamak kötü bir fikirdir. Yalnızca ele alabileceğiniz belirli istisnaları yakalamanız gerekir. Bu Stack Overflow üzerinde birçok kez geliştirilmiştir. – ChrisF

+0

Geçerli ayrıştırmadan gelen tüm verileri veya yalnızca hatalı olan satırları/öğeleri/karakterleri yok saymak ister misiniz? – hemp

+4

Ve burada bunun normal biberli pizzanın Çin yemeklerine sapma ile ilgili olacağını düşündüm. (Teslimat yapan kişiler isminizi, ne yaptığınızı ve üzerinde çalıştığınız projeler hakkında biraz bilgi sahibi olduğunda kötü mü?) – Brad

cevap

5

Ben ne soruyorsun bu olduğunu düşünüyorum :):

, bazen geçerli satır hatalı biçimlendirilmiş verileri hattı ile bir dosya hattını ayrıştırma hangi Kodunuzda bir istisnanın atılmasına neden olur. Belki de sadece kodunuzu, try/catch sadece satır okuma kodunu değil, ayrıştırma kodunu çevreleyecek şekilde yapılandırmanız gerekir. Örneğin:

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

dış try/catch bloğu açmaya veya dosyayı okumaya çalışırken bir şey oldu düzgün olursa okuyucu nesnesi kapanış idare etmektir. İç deneme/yakalama bloğu, okunan veriler hatalı biçimlendirilirse ve doğru şekilde ayrıştırılamıyorsa, istisnaları yutmaktır. Yine de, diğer herkesle aynı fikirdeyim. Sadece istisnayı yutmak iyi olmayabilir. En azından, bir yere giriş yapmanızı tavsiye ederim.

+1

Dış yakalamada, çağrı yığınını korumak için orijinal İstisnayı yenisiyle sarmak yerine 'throw; Ayrıca, 'kullanarak (okuyucu = new StreamReader (filepath))' kullanırsanız, o zaman bu dış istisna bloğuna ihtiyacınız yoktur. – hemp

+0

@hemp “Atmak”, çağrı yığınını her zaman koruyamayacak ve “eskiyi atmaya”, daha az bile olsa bahsetmeye değer. Bakınız: https://weblogs.asp.net/fmarguerie/rethrowing-exceptions-and-preserving-the-full-call-stack-trace – Dan

+0

İstisnanın atıldığı, yakalandığı durumda, haklısınız @Dan ve aynı işlevde yeniden oluşturulduğunda, yığın izi yalnızca yeniden oluşturulduğu yerle ilgili bilgileri gösterir. Pratikte bu nadir bir durumdur. – 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... 
4

Kısacası, bunun için muhtemelen istisnalar kullanmamalısınız. Bir TryParse gibi yanlış döndüren bir şey, daha verimli ve daha kolay kurtarılabilir. Özel durum işleme, künt bir nesne yaklaşımının bir parçasıdır.

MSDN Guidance on Exception Handling

+2

TryParse yalnızca, TryParse yöntemlerini sağlayan bazı ilkel türleri okuyorsanız geçerlidir. Bir dosya akışından ayrıştırma yapıyorsanız ve bu dosya eksikse istisna olmaksızın "TryParse" mümkün değildir - FileNotFoundException işlemek için * bir yerde * istisna işlemine ihtiyacınız olacaktır. –

+0

@Jason, sanırım isimleri topladın. Bir TryParse yöntemi, her yazdığınızda kullanılabilir. Hiç yazmamış olsaydın, muhtemelen yanlış yapıyorsun. MSDN, ["Tester-Doer" desenini çağırır] (http://msdn.microsoft.com/en-us/library/ms229009.aspx) ve onu tercih edilen bir uygulama olarak (kullanım dışı durumlar hariç) teşvik eder. Ayrıştırmak için bir dosya açma; bunun yerine, önce var olup olmadığını görmek için test edin, ardından okuma için açmayı deneyin, ardından açık akışı ayrıştırmayı deneyin. Bu modeli izlerseniz, bir tane atmaya karar vermedikçe FileNotFoundException gerekmez. – hemp

+1

@hemp: Bir dosyanın var olup olmadığını sınar, daha sonra okuma için açmayı deneyin, başka bir iş parçacığı veya başka bir işlem IsExists() çağrınız arasında dosyayı silen ve aslında dosyayı açan bir FileNotFound özel durumu alırsınız. Bu ne kadar nadir olursa olsun, olası istisna ile başa çıkmadığınız sürece kodunuz kusurludur. Sorun şu ki, her zaman istisna işleminden kaçınamazsınız (sevdiğim kadar). Evet, bir TryParse yöntemini yazabilirsiniz, ancak doğru bir şekilde yazmak için, hemen hemen bunun içinde bazı istisna işlemlerini de dahil etmeniz gerekecektir - sadece yakalama alanını {} hareket ettiriyorsunuz. –

2

burada bazı iyi arka plan bilgileri yok: Is there any valid reason to ever ignore a caught exception

Kısa cevap: istisnalar bu şekilde kullanmak pahalıdır. Mümkünse, girişi işlem için göndermeden önce test edin ve istisnaları göz ardı etmek yerine göz ardı etmeyin.

Ayrıca sağlamak çok geniş bir ağ oluşturarak ve hakkında bilmek isteyebileceğiniz meşru istisnalar yeme değildir. Böyle

Genelde
3

şey:

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

Belirli bir istisna genel Exception durum yakalamak önlemek ve bunun yerine yakalamak gerektiğini ne olursa olsun. Genel bir istisna yakalamak

1

bunu sadece ayrıştırma özgü hatalar için bir veya iki özel durum türlerini atmaya bekliyorsanız kötü bir fikirdir. Her belirli özel durum türünü yakalamak ve bağımsız olarak ele almak, kodunuzun başka bir (belki de beklenmedik) hatayı engellememesi için daha iyidir (örneğin, dosya eksikse veya ağ bağlantısı zaman aşımına uğramışsa) Eğer kasıtlı/gereken tüm olası hataları yakalamak ve incelikle devam etmek istiyorsanız dosyası bozuk veriler içeriyorsa aynı şekilde?)

Ancak genel bir istisna yakalamak harika bir fikir. Tüm hata türleri için işlem aynıysa (örneğin, "Herhangi bir nedenle, bu tercih değerini okuyamazsam, varsayılan 5 değerini döndürürüm" - programınızın çökmesinden sonsuz derecede daha iyi olur, çünkü siz yapmadınız çünkü) Bir ağ zaman aşımı nedeniyle bir istisna atabileceğini farketmez). Akıllıca kullanılırsa, bu yaklaşım programınızın kurşun geçirmez olmasını sağlayabilir - ancak eğer gereksiz bir şekilde kullanılırsa, bilmeniz ve düzeltmeniz gereken hataları önleyebilirsiniz ve bu çok acı verici olabilir. Herhangi istisna bastırmak zaman

, her zaman dikkatli bir şekilde hata raporlama düşünmelisiniz - Eğer bir sorun vardı kullanıcıyı söyleyeyim? Bir izleme dosyasında oturum açmanız gerekirse, bir müşteri doğru çalışmıyorsa bir şeyden şikayet ederse, sorunun kaynağına geri dönebilirsiniz? Yoksa sessizce görmezden mi geldin?Aşırı zorlu baskılar, bir programın neden öngörülemeyen bir şekilde davrandığını anlamak için çok zorlaştırabilir.

0

Siyah & beyazı gibi şeylerin göründüğüne dair bir his alıyorum ve bu doğru hissetmiyor. Evet, çoğu zaman, her şeyi yakalamak ve girdinin doğrulanması söz konusu olduğunda özensiz olmak iyi değildir. ama her zaman değil. Bu çok özel bir durum olabilir. Ne tür dosyalar ayrıştırılacağı hakkında bir şey bilmiyorum, ancak istisnalar doğru şey olabilir.

biz en iyisine karar önce, bize çok detay verirsen