Что такое пометка и сброс в BufferedReader? - PullRequest
22 голосов
/ 23 ноября 2011

Я хотел бы знать, каковы mark() и reset() методы BufferedReader?Как я их использую?Я читал Javadoc, но как новичок я не мог его понять.

Ответы [ 6 ]

14 голосов
/ 23 ноября 2011

Методы потоков mark и reset предоставляют способ перейти назад в потоке и перечитать данные.

Когда вы вызываете mark() на BufferedReader, он начинает сохранятьданные, которые вы читаете с этой точки, направляются во внутренний буфер.Когда вы вызываете reset(), он возвращается к отмеченной позиции потока, поэтому следующие read() с будут удовлетворены буфером в памяти.Когда вы прочтете за пределами этого буфера, он будет без проблем возвращаться к чтению свежих данных.BufferedInputStream работает так же.

Параметр int для mark сообщает ему максимальное количество символов (для BufferedReader) или байтов (для BufferedInputStream), которые вы хотите использовать.в обратном направлении.Если вы прочитали слишком много данных за отмеченной позицией, отметка может быть «недействительной», и вызов reset() не удастся с исключением.

Небольшой пример:

BufferedReader r = new BufferedReader(new StringReader(
    "Happy Birthday to You!\n" +
    "Happy Birthday, dear " + System.getProperty("user.name") + "!"));
r.mark(1000); // save the data we are about to read
System.out.println(r.readLine()); // read the first line
r.reset(); // jump back to the marked position
r.mark(1000); // start saving the data again
System.out.println(r.readLine()); // read the first line again
System.out.println(r.readLine()); // read the second line
r.reset(); // jump back to the marked position
System.out.println(r.readLine()); // read the first line one final time

В этом примере я обернул StringReader в BufferedReader, чтобы получить метод readLine(), но StringReader s уже поддерживают mark и reset сами по себе!Потоки, которые читают из источника данных в памяти , обычно сами поддерживают mark и reset, поскольку у них уже есть все данные в памяти, поэтому им легко снова их прочитать.Потоки, которые читают из файлов, каналов или сетевых сокетов, естественно, не поддерживают mark и reset, но вы всегда можете добавить эту функцию в любой поток, заключив ее в BufferedInputStream или BufferedReader.

9 голосов
/ 23 ноября 2011

mark(), отмечающий определенную точку в потоке, а reset() сбрасывает поток до самой последней отметки. Эти методы предоставляют функцию book-marking, которая позволяет вам читать вперед в потоке для проверки предстоящих данных.

Из этой документации:

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

6 голосов
/ 19 января 2014

Reader::mark(int readLimit) документация гласит:

Устанавливает позицию метки в этом считывателе. Параметр readLimit указывает сколько символов можно прочитать до того, как отметка станет недействительной . Вызов reset () вернет читателя обратно в отмеченную позицию если readLimit не был превзойден.

Пример:

import java.io.*;
import static java.lang.System.out;

public class App {

    public static final String TEST_STR = "Line 1\nLine 2\nLine 3\nLine 4\n";

    public static void main(String[] args) {

        try (BufferedReader in = new BufferedReader(new StringReader(TEST_STR))) {

            // first check if this Reader support mark operation
            if (in.markSupported()) {

                out.println(in.readLine());
                in.mark(0);                     // mark 'Line 2'
                out.println(in.readLine());
                out.println(in.readLine());
                in.reset();                     // reset 'Line 2'
                out.println(in.readLine());
                in.reset();                     // reset 'Line 2'
                out.println(in.readLine());
                in.mark(0);                     // mark 'Line 3'
                out.println(in.readLine());
                in.reset();                     // reset 'Line 3'
                out.println(in.readLine());
                out.println(in.readLine());
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

Выход:

Line 1
Line 2
Line 3
Line 2
Line 2
Line 3
Line 3
Line 4
1 голос
/ 23 ноября 2011

Представьте, что у вас есть следующие символы в BufferReader = "123456789", если вы пометите в позиции 4 относительно символа '5', а затем сбросите свой BufferReader, в результате вы получите 12345.

1 голос
/ 23 ноября 2011

Интерфейс Reader не позволяет вернуться, вы можете просто прочитать.BufferedReader, с другой стороны, создает буфер, так что вы можете вернуть немного при чтении.И это то, для чего предназначены эти методы.

С помощью метода mark () вы помещаете «маркер» в позицию, а затем можете читать дальше.Как только вы поймете, что хотите вернуть отмеченную позицию, вы используете для этого reset ().И с этого момента вы снова читаете те же значения.Вы можете использовать его для чего угодно.

0 голосов
/ 04 августа 2018

Вот пример.

int bufferSize = 4;
int readLimit = 4
ByteArrayInputStream byteInputStream = new ByteArrayInputStream("123456789abcdef".getBytes());
try(BufferedInputStream bufferedInputStream = new BufferedInputStream(byteInputStream, bufferSize)) {
        bufferedInputStream.mark(readLimit);
        System.out.print((char) bufferedInputStream.read());//byte1
        System.out.print((char) bufferedInputStream.read());//byte2
        System.out.print((char) bufferedInputStream.read());//byte3
        System.out.print((char) bufferedInputStream.read());//byte4
        bufferedInputStream.reset();
        System.out.print((char) bufferedInputStream.read());//byte5
        // Using this next reset() instead of the first one will throw an exception
        // bufferedInputStream.reset();

        System.out.print((char) bufferedInputStream.read());
        System.out.print((char) bufferedInputStream.read());
        System.out.print((char) bufferedInputStream.read());
    }

Выход: 12341234

Для целей readLimit, вот хорошая ссылка.

...