Нужно ли закрывать декоратор Reader из пакета java.io? - PullRequest
2 голосов
/ 29 апреля 2011

Мне нужно проанализировать объект, и мне нужно обернуть получаемый Reader в PushbackReader. Нужно ли в любом случае закрывать PushbackReader или это достаточно безопасно, чтобы оставить его открытым, поскольку это базовый считыватель (который я не открывал),

С

public static MyObject parse(Reader reader) throws IOException, ParseException {
  PushbackReader pReader = new PushbackReader(reader, PUSHBACK_SIZE);
  try {
    return parseMyObject(pReader);
  } finally {
    pReader.close();
  }
}

Или достаточно безопасно написать только следующее:

public static MyObject parse(Reader reader) throws IOException, ParseException {
  return parseMyObject(new PushbackReader(reader, PUSHBACK_SIZE));
}

Для информации, вот как я называю свой парсер:

BufferedReader reader = new BufferedReader(...);
try {
  while (...) {
    list.add(MyObjectParser.parse(reader));
  }
} catch (IOException e) {
  throw new RuntimeException("Could not read the stream", e);
} catch (ParseException e) {
  throw new ParseRuntimeException("Could not parse the stream", e);
} finally {
  // No need for null check.
  reader.close();
}

Ответы [ 3 ]

4 голосов
/ 29 апреля 2011

Вам не нужно звонить close() на PushbackReader, если вызываемый абонент закроет базовый Reader.PushbaseReader - это просто оболочка с буфером, который будет собираться мусором, когда вы закончите с ним.Вызов close() для него закроет базовый Reader, который вы захотите сохранить, если ожидаете, что метод закроет его.

Обновление : на основе вашего кодапохоже, вы не можете позвонить close() на PushbackReader, потому что это также закроет ваш базовый Reader.Следующая итерация должна завершиться неудачей, за исключением того, что поток будет закрыт, если вы это сделаете, из того, что я вижу.Например, этот пример не работает:

BufferedReader reader = new BufferedReader(new StringReader("foo"));
new PushbackReader(reader).close();
reader.read(); // IOException: Stream closed
1 голос
/ 29 апреля 2011

Это не слишком сложно, если вспомнить несколько ключевых моментов:

  • Можно закрывать поток / устройство чтения / записи более одного раза. Второе (или последующее) закрытие не действует.
  • Оболочки потока (PushBackReader, BufferedReader и т. Д.) do закрыть основной поток, когда обертка закрыта.
  • Сборщик мусора не в общем случае автоматически закрывает поток, если поток не принадлежит ресурсу ОС (дескриптор файла, сокет и т. Д.)
  • Как правило, создатель потока (используя блок try - finally) закрывает поток по завершении, например,

Reader reader = new FileReader(file);
try {
    parse(reader);
} finally {
    reader.close();
}

Таким образом, как общее правило, parse() не должен закрывать считыватель, если у него нет веских причин для этого (например, IOException оставил поток в неопределенном состоянии) в случае, если вызывающая сторона желает использовать поток для что-то еще.

Вероятно, это не конец света, если parse закроет поток, когда он закончил с ним, но если это произойдет, вам определенно следует задокументировать этот факт.

0 голосов
/ 29 апреля 2011

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

В вашем фрагменте кода это просто вопросрешая, где лежит ответственность.Кто-то должен закрыть читателя, либо метод parse, либо метод parseMyObject.Я предпочитаю метод parse, потому что тогда код более читабелен - тот же метод, который создал / открыл читатель, - тот, который закрывает его.
(в противном случае вы попадаете в странные ситуации - кто-то другой может использовать parseMyObject изатем внезапно удивитесь, что он закрыл аргумент читателя)

ОБНОВЛЕНИЕ:

Теперь, когда я вижу обновление вашего вопроса, это сводится к принятию параметра читателя вцикл, а затем оборачивая его несколько раз.Я предлагаю вам выполнить рефакторинг вашего кода, чтобы обернуть его в PushbackReader только один раз.Или переместите код инициализации читателя во внутренний метод.

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