Как мне открыть, написать и сохранить файл, избегая ошибок? - PullRequest
0 голосов
/ 21 июля 2011

Мне нужно стереть файл в моей программе.Мое решение состояло в том, чтобы иметь метод erase(), который бы делал это так:

public static void erase(String string) {
    FileWriter fw = null;
    try {
        fw  = new FileWriter(string);
        fw.write(new String());
    } catch (IOException ie) {
        e.printStackTrace();
    } finally {
        fw.flush();
        fw.close(); 
    }
}

Несколько проблем здесь:

  • Если fw работает неправильноинициализировать (по любой причине, отсутствующий файл, недопустимые разрешения и т. д.), а затем, когда я пытаюсь закрыть его в блоке finally, возникает исключение NullPointerException.

  • Если я этого не сделаюУ меня есть блок finally, тогда я могу выдать исключение NullPointerException по указанной выше причине.

  • Если я закрою файл внутри блока try, то я могу утечь ресурс, если файл откроется правильно, но неправильно пишет.

Какие еще проблемы я пропускаю и как я могу укрепить этот метод?

Ответы [ 3 ]

3 голосов
/ 21 июля 2011

Вы можете просто обернуть функциональность finally в оператор if:

if(fw != null){
    fw.close(); 
}

Это гарантирует, что если файл когда-либо был открыт, то он будет закрыт. Если он не был открыт в первую очередь, то он ничего не сделает, чего вы хотите.

Кроме того, я не уверен, так ли это для публикации, но, как правило, не рекомендуется просто печатать трассировку стека в блоке catch и продолжать («проглатывая» исключение). Вы действительно должны позволить исключению быть выданным, потому что это может скрыть ошибки и усложнить их поиск.

РЕДАКТИРОВАТЬ: см. Комментарий ниже.

1 голос
/ 21 июля 2011

Насколько мне известно, это правильный идиоматический способ написания вашего кода:

FileWriter fw = new FileWriter(string);
try {
    fw.write(new String());
    fw.flush();
} catch (IOException ie) {
    ie.printStackTrace();
} finally {
    fw.close(); 
}

Объяснение:

  • Если new FileWriter() выдает исключение, тонам не нужно ничего убирать.Метод завершается без выполнения finally.
  • . Мы должны поместить fw.flush() в try, а не в finally.Есть две причины: если запись не удалась, мы не должны беспокоиться об очистке.Кроме того, если вы вставите flush() в finally, и он выдаст исключение, то close() будет пропущено.
1 голос
/ 21 июля 2011

Включите flush() в свой основной блок и имейте только close() в улове. Затем проверьте на ноль перед закрытием:

finally {
    if(fw!=null) { fw.close(); }
    }

С помощью сброса в главном блоке вы также можете попробовать / перехватить close и записать или игнорировать любую ошибку:

finally {
    if(fw!=null) { 
        try { fw.close(); } catch(Throwable thr) { log.printError("Close failed: "+thr); thr.printStackTrace(); } 
        }
    }

или (обычно не рекомендуется):

finally {
    try { fw.close(); } catch(Throwable thr) {;}
    }

EDIT

Общая лучшая *1019* общая идиома Java для обработки ввода-вывода, IMO:

FileWriter fw=null;
try {
    fw=new FileWriter(string);
    fw.write(new String());
    fw.close();
    fw=null;
    }
catch(IOException ie) {
    // do something real here to handle the exception, or don't catch it at all.
    } 
finally {
    if(fw!=null) { 
        try { fw.close(); } catch(Throwable thr) { thr.printStackTrace(); } // now we're really out of options
        }
    }    

Это имеет важный эффект, позволяя catch перехватывать и обрабатывать исключение, выданное самим close(). (Предложение catch должно присутствовать только в том случае, если вы можете обрабатывать исключение каким-либо образом; NOT ловить и игнорировать, а обычно Вы не должны просто ловить и отслеживать.)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...