Использование метода пропуска FilterInputStream

Я хотел использовать метод пропуска класса FilterInputStream, который должен пропустить необходимое количество байтов из потока. Но в документации по методу пропуска указано http://docs.oracle.com/javase/1.4.2/docs/api/java/io/FilterInputStream.html#skip(long)

Пропускает и отбрасывает n байтов данных из входного потока. Метод пропуска может по разным причинам привести к пропуску некоторого меньшего количества байтов, например 0. Возвращается фактическое количество пропущенных байтов.

Действительно ли безопасно использовать метод пропуска для поиска определенной позиции?


person agaase    schedule 18.02.2013    source источник


Ответы (2)


Я также нахожу этот API немного проблематичным. Это оставляет слишком много свободы для конкретных реализаций:

1) Непонятно, что происходит в случае окончания потока

2) Неясно, будет ли повторный вызов skip в конце концов возвращать положительное число, когда поток непуст, или нет.

Предполагая, что вы знаете, что n не выходит за пределы конца потока, и при условии, что (2) выполняется, может быть полезен следующий код:

public static void skipSecure(InputStream is, long n) throws IOException {
    while (n >= 0) {
        long skipped = is.skip(n);
        n -= skipped;
    }
}
person Eyal Schneider    schedule 18.02.2013
comment
Возможно, мы сможем его использовать; но все же рекомендуется использовать его таким образом профессионально? - person agaase; 19.02.2013
comment
@ mivaas19: Если вы используете его для конкретной реализации InputStream, о контракте которой вы знаете, то это безопасно. Однако помните, что метод пропуска полезен только в том случае, если поток поддерживает эффективный пропуск (например, ByteArrayInputStream, который поддерживается массивом байтов в памяти, или FileInputStream, который может перепрыгивать через секторы на диске). В других случаях вы можете реализовать пропуск с помощью операций чтения. - person Eyal Schneider; 19.02.2013

FilterInputStream — это всего лишь оболочка для базового InputStream, поэтому она зависит от базового поведения InputStream.skip.

Например, если базовым InputStream является FileInputStream, нам следует обратиться к FileInputStream#skip API, в котором указано:

public long skip(long n) throws IOException

Пропускает и отбрасывает n байт данных из входного потока.

Метод skip может по разным причинам пропустить некоторое меньшее количество байтов, возможно, 0. Если n отрицательное, выдается IOException, хотя метод skip суперкласса InputStream в этом случае ничего не делает. Возвращается фактическое количество пропущенных байтов.

Этот метод может пропустить больше байтов, чем осталось в резервном файле. Это не приводит к исключению, и количество пропущенных байтов может включать некоторое количество байтов, выходящих за пределы EOF резервного файла. Попытка чтения из потока после пропуска конца приведет к тому, что -1 указывает на конец файла.

Из этого описания FileInputStream.skip мне не кажется надежным.

person Evgeniy Dorofeev    schedule 18.02.2013