2009-07-08 8 views
29

Poiché non v'è alcuna clausola finally al blocco try-catch in MATLAB, mi ritrovo a scrivere un sacco di codice come il seguente:Come gestite le risorse in MATLAB in modo eccezionalmente sicuro? (Come "try ... finally")

fid = fopen(filename); 
if fid==-1 
    error('Couldn''t open file'); 
end 
try 
    line = getl(fid); 
catch ME 
    fclose(fid); 
    rethrow ME; 
end 
fclose(fid); 

trovo avendo il fclose funziona in due posti brutti e soggetti a errori.

C'è un modo migliore per farlo?

+3

Questo è solo un punto secondario, ma suggerirei di non utilizzare la variabile "riga" nel codice. Potrebbe finire per causare qualche confusione poiché esiste già una funzione integrata chiamata LINE. – gnovice

+0

Controlla anche http://stackoverflow.com/questions/8847866/how-can-i-close-files-that-are-left-open-after-an-error –

risposta

35

Suggerirei di verificare gli oggetti ONCLEANUP. Consentono di eseguire automaticamente il codice all'uscita da una funzione (in particolare, quando l'oggetto ONCLEANUP viene cancellato dalla memoria). Loren from The MathWorks ne parla in uno dei suoi post sul blog here. Se si posiziona il codice di cui sopra in una funzione, potrebbe essere simile a questo:

function data = load_line(filename) 
    data = []; 
    fid = fopen(filename); 
    if fid == -1 
     error('Couldn''t open file'); 
    end 
    c = onCleanup(@()fclose(fid)); 
    data = getl(fid); 
end 

Anche se la chiamata a GETL genera un'eccezione, l'oggetto ONCLEANUP sarà ancora essere cancellato dalla memoria al ritorno dalla funzione load_line, assicurando così che il file venga chiuso.

+2

Grazie. Questo è esattamente quello che stavo cercando. Ho letto ancora un po 'su onCleanup e le nuove classi di stile in Matlab in generale, e mi sembra che ora con le classi handle puoi praticare RAII corretto in Matlab che è fantastico. – snth

+0

onCleanup è stato introdotto per la prima volta in MATLAB 7.6 (R2008a). Cosa suggerisci per le persone che devono mantenere la compatibilità con le versioni precedenti (in particolare, R2006b)? – rob

+1

@rob: Suggerirei di dire agli utenti di non lasciare che il loro software diventi obsoleto da 7 anni. ;) La risposta seria: dal momento che R2006b consente la programmazione orientata agli oggetti, fare in modo che una classe gestisca l'I/O dei file è come farò, come suggerito nella [risposta di Nzbuu] (http://stackoverflow.com/a/ 9024064/52738) e le risposte di [questa domanda correlata] (http://stackoverflow.com/q/8847866/52738). – gnovice

7

La mia preferenza è quella di creare una classe con un metodo delete che chiude il file quando l'oggetto esce dall'ambito. Ti dà anche l'opportunità di fare altre cose maneggevoli con file più naturali.

+0

Ulteriori spiegazioni qui - http://stackoverflow.com/questions/8847866/how-can-i-close-files-that-are-left-open-after-an-error –

+0

Hey! Questa è la mia idea;) – Nzbuu