2010-10-19 18 views
6

Sto analizzando un file con dati MalFormed di volta in volta.Mancanza di eccezioni

Ed è un'eccezione,

mi piacerebbe recuperare l'eccezione e ignorare i dati formattati male.

Qual è il modo migliore per farlo?

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

* EDIT: * penso, la mia domanda non era capito bene. mi piacerebbe recuperare dall'eccezione, qualsiasi eccezione, non voglio che il mio programma si fermi. ma per continuare.

+11

Cogliere l'eccezione generale è una cattiva idea. Dovresti solo prendere le eccezioni specifiche che puoi gestire. Questo è stato sollevato più volte su Stack Overflow. – ChrisF

+0

Vuoi ignorare tutti i dati dall'analisi corrente, o solo le linee/elementi/caratteri che sono cattivi? – hemp

+4

E qui ho pensato che sarebbe stato per deviare al cibo cinese dalla normale pizza ai peperoni. (È brutto quando i ragazzi della spedizione conoscono il tuo nome, cosa fai e un po 'dei progetti su cui stai lavorando?) – Brad

risposta

5

Penso che quello che stai chiedendo è questo:

quando analizza un file riga per riga, i dati a volte la linea attuale è valido che provoca un'eccezione nel codice. Forse hai semplicemente bisogno di strutturare il tuo codice in modo tale che try/catch circondi solo il codice di analisi, non il codice di lettura della linea. Per esempio:

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

Il blocco try/catch esterno è quello di gestire la chiusura del lettore di oggetto correttamente se è successo qualcosa quando si tenta di aprire o leggere il file. Il blocco try/catch interno è di ingerire le eccezioni sollevate se i dati letti erano malformati e non potevano essere analizzati correttamente.

Sono d'accordo con quasi tutti gli altri, però. Solo deglutire l'eccezione potrebbe non essere buono. Per lo meno, ti consiglio di registrarlo da qualche parte.

+1

Nel catch esterno, si vorrà usare 'throw; 'invece di avvolgere l'Exception originale in uno nuovo, per preservare lo stack di chiamate. Inoltre, se si usa 'using (reader = new StreamReader (filepath))' allora non è necessario quel blocco di eccezioni esterno. – hemp

+0

@hemp Vale la pena ricordare che 'throw;' non conserverà sempre lo stack delle chiamate, e 'getterà ex;' ancor meno. Vedi: https://weblogs.asp.net/fmarguerie/rethrowing-exceptions-and-preserving-the-full-call-stack-trace – Dan

+0

Hai ragione @ Dan, nel caso in cui l'eccezione viene lanciata, catturata, e ripubblicato nella stessa funzione, la traccia dello stack mostrerà solo le informazioni su dove è stato riscritto. In pratica è un caso raro. – 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

che funziona - forse si potrebbe registrare gli errori anche se troppo in caso si voleva vedere ciò che i dati è stato che ha causato l'eccezione per accadere e l'uso che per migliorare la vostra logica di analisi.

4

In breve, probabilmente non si dovrebbero usare eccezioni per questo. Qualcosa come un TryParse che restituisce false è molto più efficiente e più facile da recuperare. La gestione delle eccezioni è un approccio un po 'smussato.

MSDN Guidance on Exception Handling

+2

TryParse è rilevante solo se stai leggendo alcuni tipi primitivi che forniscono i metodi TryParse. "TryParse" senza eccezioni non è possibile se stai analizzando da un flusso di file e quel file è mancante - avrai bisogno di una gestione delle eccezioni * da qualche parte * per gestire FileNotFoundException. –

+0

@ Jason, penso che tu stia raccogliendo le lendini. Un metodo TryParse è disponibile ogni volta che ne scrivi uno. Se non ne hai mai scritto uno, probabilmente lo stai sbagliando. MSDN lo chiama modello ["Tester-Doer"] (http://msdn.microsoft.com/en-us/library/ms229009.aspx) e lo incoraggia come pratica preferita (oltre la gestione delle eccezioni). Non aprire un file per analizzarlo; invece, prima prova per vedere se esiste, quindi prova ad aprirlo per la lettura, quindi prova ad analizzare lo stream aperto. Se segui questo schema, non è necessario alcun FileNotFoundException, a meno che tu non decida di lanciarne uno. – hemp

+1

@hemp: se si verifica se esiste un file, quindi si tenta di aprirlo per la lettura, si otterrà un'eccezione FileNotFound quando un altro thread o un altro processo elimina il file tra la chiamata IsExists() e effettivamente l'apertura del file. Non importa quanto raro sia, il tuo codice è imperfetto a meno che tu non abbia a che fare con la possibile eccezione. Il problema è che * non puoi * evitare sempre la gestione delle eccezioni (proprio come mi piacerebbe). Sì, puoi scrivere un metodo TryParse, ma per scriverlo correttamente, dovrai quasi certamente includere alcune eccezioni all'interno di esso - stai semplicemente spostando il sito del catch {}. –

2

C'è qualche buon background informazioni qui: Is there any valid reason to ever ignore a caught exception

Risposta breve: eccezioni sono costosi da utilizzare in questo modo. Se possibile, testare l'input prima di inviarlo per l'elaborazione e ignorarlo, invece di ignorare le eccezioni.

Assicurati inoltre di non gettare una rete troppo ampia e di mangiare le eccezioni legittime che potresti voler conoscere.

3

In generale, qualcosa di simile:

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

Si dovrebbe evitare la cattura il generale Exception caso e invece prendere una deroga specifica, qualunque essa sia.

1

Rilevare un'eccezione generale è una cattiva idea se ci si aspetta che lanci solo uno o due tipi di eccezione specifici per errori specifici dell'analisi. Solitamente è meglio catturare ogni specifico tipo di eccezione e gestirlo in modo indipendente in modo che il codice non sopprima altri (forse imprevisti) errori (ad esempio se il file è mancante o una connessione di rete è scaduta, dovrebbe essere gestito nel stesso modo come se il file contiene dati corrotti?)

Tuttavia, la cattura di un'eccezione generale è una grande idea se si desidera/vuole volutamente cogliere tutti gli errori possibili e continuare con garbo. Questo può accadere se la gestione di tutti i tipi di errore è la stessa (ad esempio "se, per qualsiasi motivo, non riesco a leggere questo valore di preferenza, restituirò il valore predefinito di 5" - è infinitamente migliore del tuo arresto anomalo del programma perché non hai mi rendo conto che potrebbe generare un'eccezione a causa di un timeout di rete). Se usato con saggezza, questo approccio può rendere il tuo programma a prova di proiettile, ma se usato in modo incauto puoi sopprimere gli errori che devi conoscere e risolvere, e questo può essere molto doloroso.

Quando si sopprime qualsiasi eccezione, si dovrebbe sempre considerare attentamente la segnalazione degli errori - si dovrebbe dire all'utente che si è verificato un problema? Dovresti registrarlo in un file di traccia in modo che quando un cliente si lamenta di qualcosa che non funziona correttamente, puoi rintracciare l'origine del problema? O dovresti ignorarlo silenziosamente?Basta fare attenzione poiché le soppressioni troppo zelanti possono rendere molto difficile capire perché un programma si sta comportando in modo imprevedibile.

0

Ho la sensazione che si vedano cose come il nero & bianco, e questo non sembra giusto .. Sì, il più delle volte, non è buono prendere tutto ed essere sciatto quando si tratta di convalida dell'input, ma non sempre. Questo potrebbe benissimo essere un caso speciale. Non so nulla sul tipo di file che verranno analizzati, ma le eccezioni potrebbero essere la cosa giusta.

Prima di decidere ciò che è meglio, darci maggiori dettagli :)