2017-02-22 40 views
1

Я новичок в потоках Java, я хотел бы прочитать содержимое определенных файлов, а затем прочитать его с самого начала. Я создал BufferedInputStream и я запутался о документации BufferedInputStream.mark (интермедиат markLimit)Что такое ограничение чтения меток в bufferedinputstream

Документация говорит:

public void mark(int readlimit) 

Этот метод отмечает положение в входе которого поток может «сбросить», вызвав метод reset(). Параметр readlimit - это количество байтов, которое может быть прочитано из потока после установки знака до того, как метка станет недействительной. Например, если вызов mark() вызывается с пределом чтения в 10, то, когда 11 байтов данных считываются из потока до вызова метода reset(), метка недействительна, и экземпляр объекта потока не требуется помните отметку.

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

Заменяет: марки в классе FilterInputStream

Параметры: readlimit - количество байт, которые могут быть считаны до отметки становится недействительным **

Моего кода:

public class Test { 
    public static void main(String[] args) throws IOException { 

     File resource = new File("beforeFix.txt");   
     FileInputStream fileInputStream = new FileInputStream(resource); 
     BufferedInputStream bufferedInputStream = new BufferedInputStream(fileInputStream); 
     int i = bufferedInputStream.read(); 
     bufferedInputStream.mark(1); 
     i = bufferedInputStream.read(); 
     i = bufferedInputStream.read(); 
     i = bufferedInputStream.read(); 
     i = bufferedInputStream.read(); 
     i = bufferedInputStream.read(); 
     i = bufferedInputStream.read(); 
     i = bufferedInputStream.read(); 
     i = bufferedInputStream.read(); 
     i = bufferedInputStream.read(); 
     i = bufferedInputStream.read(); 
     i = bufferedInputStream.read(); 
     i = bufferedInputStream.read(); 
     i = bufferedInputStream.read(); 
     i = bufferedInputStream.read(); 
     i = bufferedInputStream.read(); 
     i = bufferedInputStream.read(); 
     i = bufferedInputStream.read(); 
     i = bufferedInputStream.read(); 
     i = bufferedInputStream.read(); 
     i = bufferedInputStream.read(); 
     bufferedInputStream.reset(); 
     i = bufferedInputStream.read(); 
     i = bufferedInputStream.read(); 
     i = bufferedInputStream.read(); 
     i = bufferedInputStream.read(); 
     bufferedInputStream.reset(); 
    } 
} 

В приведенном выше коде я установил метку отметки как 1, но знак не становится недействительным в соответствии с документацией.

Может ли кто-нибудь четко объяснить мне, какова фактическая цель установки этого с помощью небольшого примера?

Заранее спасибо

+0

, когда я звоню сброс(), он не бросил никаких исключений для меня. В соответствии с документацией отметка должна быть недействительной после того, как я прочитал второй байт, так как я установил ограничение метки на 1, но это не так. Итак, какова цель этого знака()? –

+0

Используйте форматирование цитаты для цитируемого текста. И, пожалуйста, уберите жирный шрифт. Это больно глазам. – EJP

ответ

1

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

Итак, если вы намерены прочитать 100 байт перед вызовом сброса, то ваш буфер должен быть как минимум 100 байт, и именно так вы должны вызывать метку.

bufferedInputStream.mark(200); 

... read no more than 200 bytes ... 

bufferedInputStream.reset(); // reset back to marked position 

Update

Похоже документации mark не соответствует фактическому поведению. В документации говорится:

the maximum limit of bytes that can be read before the mark position becomes invalid 

Однако, похоже, что он должен быть the minimum limit, или, по крайней мере, лежащие в основе реализации не требуется отказаться от знака, как только предел чтения превышен, если они все еще могут поддерживать сброс к отмеченной позиции.

+0

В приведенном выше примере (который я предоставил), я установил ограничение метки равным 1 и считал байты более одного. В соответствии с документацией отметка должна быть недействительной после того, как я прочитал второй байт, так как я установил ограничение метки на 1, но это не так. Итак, какова цель этого знака()? –

+0

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

+0

«Минимальный предел» не имеет смысла. Конечно, вам не нужно читать столько байтов, прежде чем вызывать 'reset()'. – Holger

0

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

Однако поток не требуется запоминать какие-либо данные на всех, если более чем readlimit байт считываются из потока перед reset называется.

«не требуется» не означает, что «не разрешено». В спецификации просто указано, чего вы не можете ожидать, чтобы всегда работать, в ней не указано, что вы можете ожидать всегда.

В случае BufferedInputStream, легко объяснить, что происходит под капотом. Каждый из BufferedInputStream имеет емкость, default - 8192, и он всегда может сбрасывать прошлое столько же байтов, сколько и его текущая емкость буфера. Указав более высокий предел, вы будете вынуждены распределять более крупный буфер при необходимости, чтобы выполнить гарантию.

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

Это легко изменить свой пример, чтобы сделать это не в состоянии воспроизводимая:

File resource = new File("beforeFix.txt");   
FileInputStream fileInputStream = new FileInputStream(resource); 
BufferedInputStream bufferedInputStream = new BufferedInputStream(fileInputStream, 1); 
int i = bufferedInputStream.read(); 
bufferedInputStream.mark(1); 
i = bufferedInputStream.read(); 
i = bufferedInputStream.read(); 
bufferedInputStream.reset(); // will fail 
+0

В документах также говорится следующее: «максимальный предел байтов, который может быть прочитан до того, как позиция метки станет недействительной», но она не станет всегда недействительным, что является проблемой OP. Он не читает «** может ** стать недействительным». – john16384

+0

@ john16384: концептуально знак * * недействителен, так как вы не можете положиться на него. Возникает другой вопрос, какие последствия возникают. В документации [reset() '] (https://docs.oracle.com/javase/8/docs/api/java/io/InputStream.html#reset--) четко сказано:« Если ... количество байты, считанные из потока, поскольку последний вызов 'mark' больше, чем аргумент' mark' при последнем вызове, тогда может быть выведено 'IOException' **.« Вы видите, «* может быть *», не "* гарантированно будет *" ... – Holger

+0

Хорошо, это хорошая находка. – john16384