Я пытаюсь генерировать автоматизированные входы в System.in и хотел бы иметь возможность читать последующие токены в потоке различными сканерами в произвольные моменты времени:
// save System.in for later restoration
InputStream inTemp = System.in;
// create an input
String input = "15 3";
// push input into InputStream
InputStream bais = new ByteArrayInputStream(input.getBytes());
// deviate System.in
System.setIn(bais);
Scanner s1 = new Scanner(System.in);
// the nextInt should only read the "15" from the input
int i1 = s1.nextInt();
System.out.println("#1: " + i1 * 2);
Scanner s2 = new Scanner(System.in);
// the nextInt should read the "3" from the input
int i2 = s2.nextInt();
System.out.println("#2: " + i2 * 2);
// restore System.in
System.setIn(inTemp);
К сожалению, сканер s1 превентивно считывает весь контент потока вместо того, чтобы читать только первый токен. Таким образом, второй сканер s2 находит пустой ввод.
Вышеприведенный код представляет собой крайне упрощенную реальную ситуацию: часть, в которой используются сканеры, не отвечает моей ответственности. Он создается учащимися, которые представляют свои классы в нашу экзаменационную систему. Наша система вызывает методы учеников после заполнения System.in тестовыми данными. Поэтому мы не можем влиять на то, как используются сканеры. BTW: закрытие сканера не поможет. Первый сканер просто считывает слишком много данных из потока.
На самом деле, я вижу несколько возможных способов:
Поместите маркеры на вход, которые не позволяют сканеру читать дальше.
Расширьте ByteArrayInputStream таким образом, чтобы он показывал только один токен за попытку. Это, вероятно, означает манипулирование выводами доступных() -method, pos-атрибутов и содержимого buf Stream, а также для отслеживания количества показаний, выполняемых сканером. Тем не менее, сканер продолжает запрашивать данные, независимо от того, сколько жетонов он должен читать. Кто-нибудь сделал это раньше?
Используйте другой поток, который обеспечивает функциональность, описанную под 2 (или что-то подобное).
Попросите учащихся прочитать данные из Сканера с помощью другого метода (вместо nextInt), который будет вести себя так, как требуется. Есть ли такой метод? Я его не нашел.
Я уже начал манипулировать этим поведением, расширив ByteArrayInputStream, но не зашел слишком далеко, поскольку я думал, что это может быть концептуально слишком сложный подход.
Любая помощь приветствуется.
С наилучшими пожеланиями, Томас
Я думаю, что ответ... Нет.
Невозможно предотвратить Scanner
вперед и буферизацию символов, а также не заставить его "возвращать" символы, которые он буферизует. (Действительно, если источник, который вы читали, не поддерживал методы меток/сброса или pushback, было бы невозможно "вернуть" символы.)
Вам нужно будет пересмотреть свой подход к тестированию. Повторное использование экземпляра Scanner
.
Другая альтернатива - реализовать собственную версию Scanner
... что позволяет вам "возвращать" буферные символы.
Попробуйте закрыть первый сканер после первого чтения. Это должно остановить первый сканер и позволить второму сканеру читать следующую переменную.
ByteArrayInputStream
.
ByteArrayInputStream
таким образом, чтобы онScanner.nextInt()
только один токен на вызовScanner.nextInt()
. При этом мне не нужно менять настройку для студентов или учить их каким-то особым правилам программирования, чтобы удовлетворить наш подход к тестированию. Сложнее всего, вероятно, провести различие междуScanner
читающим впереди, иScanner
читающим следующий токен.Scanner
. НАСКОЛЬКО МНЕ ИЗВЕСТНО.