Возврат InputStream из открытого метода

у меня есть класс, где с одной стороны, это кажется правильным возвратить InputStream из открытого метода, например

public class MyClass {

    private File _file;

    ...

    public InputStream getInputStream() {
        return new FileInputStream( _file );
    }
}

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

4 ответов


зависит от того, почему это проблема в ваших глазах. Если вы абсолютно должны вернуть InputStream и файл, о котором идет речь, не слишком велик, вы можете буферизировать весь файл в массив байтов, закрыть исходный поток и return new ByteArrayInputStream(buf). Закрытие ByteArrayInputStream не нужно (и на самом деле не имеет никакого эффекта).

однако, если он "чувствует себя хорошо", чтобы возвратить InputStream, не имеет смысла, что вызывающий должен быть ожидал an InputStream, и все, что с ним связано, включая необходимость закрытия потока, когда закончите?


возвращение InputStream не является изначально плохой вещью. Теперь, если вы хотите, чтобы ваш вызывающий абонент получил доступ к данным без ответственности за закрытие ресурса, вы можете сделать это:

interface InputReader {
    void readInput(InputStream is);
}
public class MyClass {
    void feed(InputReader ir){
       try(InputStream is=new FileInputStream( _file )){
          ir.readInput(is);
       }
    }
}

вызывающий объект указывает экземпляр InputReader который получит закрываемый ресурс в качестве аргумента и больше не несет ответственности за его закрытие.

MyClass myClass = ... ; //Get the instance
myClass.feed( new InputReader() {
    @Override
    void readInput(InputStream is){
       ... ; // Use at will without closing
    }
});

следует рассмотреть, чтобы украсить InputStream прежде чем передать его в InputReader, Так что .close() броски и исключение.


реалистично нет ничего, что вы можете сделать, не зная больше деталей о классе. Вы можете обеспечить обработку файлов с помощью методов в MyClass (что требует знания содержимого файла) и закрыть поток, когда он пуст. Кроме того, пользователь класса несет ответственность за этот объект, и вы не можете этого избежать. Без возможности деструкторов, как в C++, вы не можете быть на 100% ответственны за любой объект, который вы позволяете покинуть область вашего класс.

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


...поскольку это накладывает бремя на вызывающего абонента, чтобы закрыть этот поток.

да, вызывающий отвечает за обработку операции закрытия возвращаемого потока(ов). Поскольку ваш метод не может отслеживать возвращенную вещь,эта задача полностью принадлежит абоненту. Существует аналогия между этим случаем и использованием исключений. Разработчики используют исключения, потому что авторы API не всегда могут контролировать то, что они представляют нам. Мы должны быть осторожно, например, когда есть возможность деления числа на ноль.