Java: IOException при записи в ByteArrayOutputStream? - PullRequest
9 голосов
/ 08 июня 2011

Поскольку ByteArrayOutputStream просто записывает в память, IOException никогда не должно возникать.Однако из-за контракта интерфейса OutputStream все потоковые операции определяют IOException в своем предложении throws.

Как правильно обработать этот никогда не встречающийся IOException?Просто обернуть операции в пустой блок try-catch?

Или есть ли реальные ситуации, когда ByteArrayOutputStream может вызвать исключение?

(См. Также: Как я могу обработать IOException, которое, как я знаю, никогда не может быть сгенерировано безопасным и читабельным способом? )

РЕДАКТИРОВАТЬ

Как указывает Джон, ByteArrayOutputStream не объявляет предложение throws для определяемых им write методов - однако оно наследует write(byte[]) от OutputStream, и это делаетthrow IOEXception (довольно странно, что BAOS не переопределит этот метод, поскольку он может заменить версию суперкласса - которая записывает один байт за раз - гораздо более эффективным вызовом arraycopy)

Ответы [ 6 ]

10 голосов
/ 08 июня 2011

Ну, ByteArrayOutputStream не заявляет, что любой из его методов выдает IOException, кроме writeTo и close. (Я не знаю, почему close все еще заявляет об этом, если честно.)

Если у вас есть ссылка типа OutputStream, вы, конечно, все равно увидите объявления throws из этого.

Я бы не использовал пустой блок catch - я бы выбросил что-то вроде IllegalStateException или похожее непроверенное исключение: это означает, что вы находитесь в ситуации, которую вы действительно не ожидаете, и что-то пошло не так.

2 голосов
/ 08 июня 2011

Я только что заметил, что ByteArrayOutputStream.write на самом деле не объявляет IOException - но Eclipse жалуется на необработанное исключение всякий раз, когда я его использую ... странно.

Это легкообъяснить.Вы, вероятно, сделали что-то вроде этого:

    OutputStream os = new ByteArrayOutputStream();
    ...
    os.write();

«Проблема» в том, что вы вызываете метод как OutputStream.write(), а не как ByteArrayOutputStream.write().Таким образом, компилятор говорит:

«А ... write() на OutputStream может бросить IOException, так что вы должны с этим справиться».

Он не может сказать:

"Этот конкретный OutputStream действительно ByteArrayOutputStream ... поэтому мы вас отпустим."

, потому что JLSне позволяет этого.

Это один из тех крайних случаев, когда следование «наилучшей практике» путем кодирования интерфейса, а не класса реализации возвращается к вам.

ОК, так что ...

  • это мягкий зазор, а не полный прикус.
  • OutputStream реализован как класс Javaне интерфейс Java, но это не относится к делу.
  • большинство компиляторов на самом деле не поддерживают с вами беседы во время компиляции кода: -)

1 голос
/ 13 сентября 2018

Начиная с Java 11, существует также новый метод ByteArrayOutputStream.writeBytes(byte[]), который также не генерирует IOException:

/**
 * Writes the complete contents of the specified byte array
 * to this {@code ByteArrayOutputStream}.
 *
 * ...
 *
 * @since   11
 */
public void writeBytes(byte b[]) {
    write(b, 0, b.length);
}

Вы можете использовать этот метод, если нене хочу обрабатывать IOException, который никогда не выбрасывается.

1 голос
/ 07 июня 2018

Существует улучшение ticket для этой проблемы с 2002 года. Причина, по которой это не устраняется, заключается в том, что это повлияет на совместимость с предыдущими версиями Java.

Здесь следуют 2 обходных пути, которые я бы рассмотрел.

Обходной путь 1

Метод write(byte[], int, int) не генерирует проверенные исключения. Несколько более детально указать 2 дополнительных параметра. Но все-таки занимаемая площадь меньше без пробной зацепки.

baos.write(array, 0, array.length);

Обходной путь 2

Другое возможное решение - написать свой ByteUtil класс , который перехватит внутреннее исключение.

public final class ByteUtil
{
  public static void write(ByteArrayOutputStream baos, byte[] bytes)
  {
    try
    {
      baos.write(bytes);
    }
    catch (IOException e)
    {
      // impossible
    }
  }
}

// usage
ByteUtil.write(baos, bytes);
1 голос
/ 08 июня 2011

Цепочка исключений - лучшая практика в этой ситуации. т.е. генерируем исключение RuntimeException.

1 голос
/ 08 июня 2011

Типичным клише является throw new RuntimeException(theIOException) в блоке catch.Если случится невозможное, вы хотя бы узнаете об этом.

...