Как безопасно отменить чтение InputStream? - PullRequest
1 голос
/ 14 февраля 2011

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

Вот что у меня так далеко:

ByteArrayOutputStream buffer = new ByteArrayOutputStream();

int nRead;
byte[] byteData = new byte[16384];

while ((nRead = inputStream.read(byteData, 0, byteData.length)) != -1){

    if(buffer.size() <= MAX_FILE_SIZE){
        buffer.write(byteData, 0, nRead);
    }

}

if(buffer.size() <= MAX_FILE_SIZE){
    buffer.flush();
    mData = buffer.toByteArray();
}

inputStream.close();

Спасибо

Ответы [ 2 ]

5 голосов
/ 14 февраля 2011

Вызов close() делает то, что вы хотите, относительно JVM и ее ресурсов.

Однако в некоторых случаях это может иметь нежелательные последствия. Например, если входной поток (в конечном счете) является потоком сокета, то закрытие потока закрывает сокет, и выполнение take может привести к тому, что удаленный сервер, отправляющий данные, увидит сетевую ошибку. (Это, вероятно, не имеет значения, но если оно не обрабатывается должным образом, вы можете увидеть исключения в лог-файле удаленного веб-сервера.)


Даже если это было в середине чтения и не заканчивается?

Да. Все данные, находящиеся «в полете» , будут выброшены.

  • Закрывая дескриптор сокета, это приложение неявно говорит, что оно больше не интересуется данными.
  • При обычных обстоятельствах 1 , ничто иное не имеет дескриптора сокета, который позволяет ему читать эти данные.
  • Больше ничего нельзя переподключить к сокету. Это не поддерживается API сокетов ... на уровне операционной системы.
  • Поэтому нет смысла «хранить» данные.

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

Кроме того, нужно ли как-то отменять или закрывать буфер.

Так как это ByteArrayOutputStream, Нет. Потоки, которые читают / записывают в буферы в памяти (байтовые массивы, StringBuffers), не должны закрываться 2 . GC может восстанавливать чисто ресурсы памяти без каких-либо проблем. Также BufferedInput/OutputStream не нужно закрывать , если поток, который он оборачивает, не нуждается в закрытии.


1 - Я думаю, что для Linux / Unix возможно открыть сокет и передать его разветвленному дочернему процессу. Однако и родительский и дочерний процессы нецелесообразно использовать сокет из-за сложности координации их использования. Более того, вы не можете делать такие вещи между процессами Java, потому что API Java Process не позволяет этого.

2 - Единственный гипотетический случай, когда это неверно, - это когда буфер представляет собой NIO Buffer, поддерживаемый сегментом разделяемой памяти или отображенным в память файлом ... который является мусором коллекционер может быть не в состоянии вернуть своевременно. И я говорю гипотетически, потому что я не думаю, что есть готовые потоковые оболочки для объектов NIO Buffer.

1 голос
/ 14 февраля 2011

close() безопасен и высвобождает ресурсы: http://download.oracle.com/javase/6/docs/api/java/io/InputStream.html#close%28%29

Это все, что вам нужно сделать для этого.Это освобождает все ресурсы JVM.Если это связано с сокетом, этот сокет будет закрыт.Операционная система (транспортный уровень IOW) просто отбрасывает все буферы, ожидающие пакеты и т. Д. На другом конце соединения (отправитель) может появиться ошибка, но в любом случае ее следует подготовить.

...