Попробуйте... поймать внутри, наконец, при выпуске ресурса?

Я хочу написать String в файл Unicode. Мой код в Java:

public static boolean saveStringToFile(String fileName, String text) {
    BufferedWriter out = null;
    boolean result = true;
    try {
        File f = new File(fileName);
        out = new BufferedWriter(new OutputStreamWriter(
                new FileOutputStream(f), "UTF-8"));
        out.write(text);
        out.flush();
    } catch (Exception ex) {
        result = false;
    } finally {
        if (out != null)
            try {
                out.close();
            } catch (IOException e) {
                // nothing to do! couldn't close
            }
    }

    return result;
}

Update

Теперь сравните его с С#:

    private static bool SaveStringToFile(string fileName, string text)
    {
        using (StreamWriter writer = new StreamWriter(fileName))
        {
            writer.Write(text);
        }
    }
Форма

или даже try..catch будет:

    private static bool SaveStringToFile(string fileName, string text)
    {
        StreamWriter writer = new StreamWriter(fileName);
        try
        {
            writer.Write(text);
        }catch (Exception ex)
        {
            return false;
        }
        finally
        {
            if (writer != null)
                writer.Dispose();
        }
    }

Возможно, это потому, что я из мира С# и .Net. Но это правильный способ написать String в файл? Это слишком много кода для такой простой задачи. В С# я бы сказал просто out.close();, и это было так, но кажется немного странным добавить try..catch внутри оператора finally. Я добавил оператор finally, чтобы закрыть файл (ресурс) независимо от того, что произойдет. Во избежание использования слишком большого ресурса. Правильно ли это на Java? Если да, почему close выдает исключение?

Ответ 1

Вы правы в том, что вам нужно вызвать close() в блоке finally, и вам также необходимо обернуть это try/catch

Как правило, вы пишете полезный метод в проекте или используете метод утилиты из библиотеки, например http://commons.apache.org/io/apidocs/org/apache/commons/io/IOUtils.html#closeQuietly(java.io.Closeable), чтобы закрыть Quietly.i.e. игнорировать любое исключение throw из объекта close().

Еще одна заметка: Java 7 добавила поддержку для попыток с ресурсами, которая устраняет необходимость вручную закрыть resouce - http://docs.oracle.com/javase/tutorial/essential/exceptions/tryResourceClose.html

Ответ 2

Да, нет ничего странного в том, что Try catch in finally() в java. close() может вызывать исключение IoException по разным причинам, поэтому он должен быть заключен в блоки try catch. Существует усовершенствованное решение этой проблемы, в последней версии java SE 7 Попробуйте с ресурсами

Ответ 3

Java-эквивалент оператора using - это оператор try-with-resources, добавленный в Java 7:

public static void saveStringToFile(String fileName, String text) throws IOException {
    try (Writer w = new OutputStreamWriter(new FileOutputStream(fileName), "UTF-8")) {
        w.write(text);
    }
}

С помощью try-in-resources будет автоматически закрываться поток (который сжимает его), и бросать любые исключения, возникающие при этом.

BufferedWriter не требуется, если вы все равно производите один вызов (его цель состоит в объединении нескольких записей в базовый поток для уменьшения количества системных вызовов, что повышает производительность).

Если вы настаиваете на обработке ошибок, возвращая false, вы можете добавить предложение catch:

public static boolean saveStringToFile(String fileName, String text) {
    try (Writer w = new OutputStreamWriter(new FileOutputStream(fileName), "UTF-8")) {
        w.write(text);
        return true;
    } catch (IOException e) {
        return false;
    }
}

Ответ 4

Это должно сделать трюк. Если вы хотите управлять исключением со сложным поведением - создайте StreamWriter

public static bool saveStringToFile(String fileName, String text) 
{
    try
    {
        File.WriteAllText(fileName, text, Encoding.UTF8);
    }
    catch (IOException exp)
    {
        return false;
    }
    return true;
}

Ответ 5

Итак, в чем вопрос? Нет правильного или неправильного пути. Может закрыть даже выбросить исключение IO? Что вы делаете тогда? Мне вообще нравится не реинтронирование любого рода.

Проблема в том, что вы просто проглатываете исключение IO при закрытии - хорошо. Можете ли вы жить с этим дутьем? Если нет, у вас есть проблема, если да - ничего плохого.

Я никогда этого не делал, но, опять же, это зависит от вашего бизнес-случая.

Ответ 6

arch = new File("path + name");
arch.createNewFile();
FileOutputStream fos = new FileOutputStream(arch);
fos.write("ur text");
fos.close();

мой путь.

Ответ 7

Лучший способ избежать этого - поместить ваш out.close() после out.flush(), и процесс автоматически обрабатывается, если сбой завершается. Или используйте это лучше (что я использую):

File file = ...
   OutputStream out = null;
   try {
     out = new BufferedOutputStream(new FileOutputStream(file));
     ...
    finally {
     if (out != null) {
       out.close();
     }
   }
 }

Ответ 8

Если вам нужен минимальный код, вы можете использовать FileUtils.writeStringToFile

FileUtils.writeStringToFile(new File(fileName), text);

и я бы не использовал boolean, так как редко можно было игнорировать либо тот факт, что произошла ошибка, либо причина, по которой она возникла в сообщении об исключении. Использование проверенного Exception гарантирует, что вызывающий абонент всегда будет правильно обрабатывать такую ​​ошибку и может регистрировать осмысленные сообщения об ошибках относительно того, почему.

Чтобы сохранить файл с помощью специального CharSet

try {
    FileUtils.writeStringToFile(new File(fileName), text, "UTF-8");
} catch(IOException ioe) {
    Logger.getLogger(getClass()).log(Level.WARNING, "Failed to write to " + fileName, ioe);
}