InputStream, mark(), reset()
Как методы mark()
и reset()
работают в точности (в коде ниже), шаг за шагом? Я попытался написать свой собственный пример, но начинает бросать ошибочное исключение или похожее на него, и я не могу понять, в чем смысл размещения меток и reset методов в этом коде, потому что я не вижу разницы с этим или без.
import java.io.*;
class BufferedInputStreamDemo {
public static void main(String args[]) {
String s = "© is a copyright symbol, "
+ "however © isn't.\n";
byte buf[] = s.getBytes();
ByteArrayInputStream in = new ByteArrayInputStream(buf);
int c;
boolean marked = false;
//try_with_resources
try (BufferedInputStream f = new BufferedInputStream(in)) {
while ((c = f.read()) != -1) {
switch (c) {
case '&':
if (!marked) {
f.mark(32);
marked = true;
} else {
marked = false;
}
break;
case ';':
if (marked) {
marked = false;
System.out.print("(c)");
} else
System.out.print((char) c);
break;
case ' ':
if (marked) {
marked = false;
f.reset();
System.out.print("&");
} else
System.out.print((char) c);
break;
default:
if (!marked)
System.out.print((char) c);
break;
}
}
} catch (IOException e) {
System.out.println("I/O Error: " + e);
}
}
}
Ответы
Ответ 1
Когда f.mark(32);
достигнут, курсор чтения уже после &
, и маркер установлен для reset
, чтобы узнать, куда отскакивать. Поэтому, когда вы обнаружили, что для закрытия элемента отсутствует ;
, вы вручную печатаете &
и перемещаете курсор чтения назад (после &
, где был помещен маркер, с помощью вызова mark(32)
), используя метод reset
. При следующем чтении, поскольку ваша переменная marked
не установлена, она будет печатать символы.
mark(32)
означает автоматическое удаление маркера, если ваш курсор чтения будет превышать 32 символа. Это может быть проблемой в вашем другом коде, что вызывает ошибку, поскольку маркер уже недействителен.
Ответ 2
См. документацию по API:
mark(int)
Отмечает текущую позицию в этом входном потоке. Последующий вызов метода reset репозиционирует этот поток в последней помеченной позиции, чтобы последующие чтения перечитывали одни и те же байты.
Аргумент readlimit указывает этому входному потоку, чтобы позволить многим байтам считываться до того, как позиция метки становится недействительной.
Этот метод просто выполняет in.mark(readlimit).
reset()
Переводит этот поток в позицию во время последнего вызова метода меток на этот входной поток.
Этот метод просто выполняет in.reset().
Знаки потока предназначены для использования в ситуациях, когда вам нужно немного прочитать немного, чтобы увидеть, что в потоке. Часто это проще всего сделать, вызвав некоторый общий синтаксический анализатор. Если поток относится к типу, обрабатываемому синтаксическим разбором, он просто радуется счастливо. Если поток не относится к этому типу, синтаксический анализатор должен выдавать исключение, когда он терпит неудачу. Если это происходит в пределах readlimit bytes, это позволяет внешнему коду reset потоку и попробовать другой синтаксический анализатор.