Главная » Java » Класс Seq uenceInputStream

0

Класс SequenceInputStream создает единый входной поток, читая данные из одного или нескольких входных потоков: сначала первый поток читается до самого конца, затем — следующий за ним, и так далее, до последнего потока. Этот класс содержит два конструктора: один — для простейшего случая двух входных потоков, которые передаются в качестве параметров конструктора; другой конструктор предназначен для произвольного количества входных потоков, в нем используется абстрактное представление Enumeration, описанное в главе 12. Реализация интерфейса Enumeration позволяет получить упорядоченный список объектов любого типа. Для потока Sequence InputStream перечисление может содержать только объекты типа Input Stream. Если в нем окажется что-либо еще, то при попытке получения объекта из списка возбуждается исключение SequenceInputStream.

Например, приложение Factor вызывает метод factor Numbers для каждого аргумента, входящего в командную строку. Все числа обрабатываются отдельно, так что подобное разобщение параметров не имеет особого значения. Тем не менее, если бы ваше приложение суммировало числа из входного потока, то было бы необходимо собрать все значения воедино. В приведенном ниже приложении SequenceInputStream используется для создания единого потока из объектов StringBufferInputStream для каждого из параметров:

import java.io.*;

import java.util.Vector;

class Sum {

public static void main(String[] args) {

InputStream in;  // поток, из которого читаются числа

if (args.length == 0) {

in = System.in;

} else {

InputStream stringIn;

Vector inputs = new Vector(args.length);

for (int i = 0; i << args.length; i++) { String arg = args[i] + " ";

stringIn = new StringBufferInputStream(arg);

inputs.addElement(stringIn);

}

in = new SequenceInputStream(inputs.elements());

}

try {

double total = sumStream(in); System.out.println("The sum is " + total);

} catch (IOException e) { System.out.println(e); System.exit(-1); //

}

}

// …

}

Если параметры отсутствуют, то для ввода данных используется System.in. В противном случае создается объект Vector, размер которого позволяет хранить столько объектов StringBufferInputStream, сколько аргументов в командной строке. Затем мы создаем поток для каждого из аргументов и добавляем в концы строк пробелы, чтобы разделить их. Затем потоки заносятся в вектор streams. После завершения цикла мы вызываем метод elements вектора, чтобы получить объект Enumeration с элементами. Enumeration используется в конструкторе SequenceInputStream, который сцепляет все потоки параметров в единый поток InputStream. Затем все числа в этом потоке суммируются методом sumStream и выводится результат. Реализация sumStream приведена в примере из раздела “Класс StreamTokenizer”. /Конечно, проблему можно было решить и иначе – получить единую строку, в которую входят все параметры, и создать один поток StringBufferInputStream./

Кроме того, можно было создать и новую реализацию Enumeration, которая бы обращалась за каждым аргументом к потоку StringInputStream.  Подробности приведены в разделе “Интерфейс Enumeration”.

11.13. Класс LineNumberInputStream

Объекты класса LineNumberInputStream позволяют следить за нумерацией строк во время чтения данных из входного потока. Метод getLine Number, возвращает текущий номер строки. Нумерация строк начинается с единицы.

Текущий номер строки может быть задан методом setLineNumber. Это может оказаться полезным, когда вы работаете с несколькими входными потоками как с одним целым, однако нумерация строк должна осуществляться относительно начала каждого из потоков. Например, если SequenceInput Stream используется для чтения из нескольких файлов как из одного потока, то может возникнуть надобность в отдельной нумерации строк для каждого из файлов, из которого поступили данные.

Упражнение 11.5

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

Программа должна выводить каждую строку, в которой встретилось это слово, и ее номер.

11.14. Класс PushbackInputStream

Класс PushbackInputStream обеспечивает возможность отката на один символ потока назад. Это особенно полезно при разделении входного потока на отдельные лексемы. Например, чтобы определить, где кончается лексема, часто приходится читать символ, следующий за ее концом. После просмотра символа, завершающего текущую лексему, необходимо вернуть его во входной поток, чтобы он послужил началом следующей лексемы. В приведенном ниже примере класс PushbackInputStream используется для поиска самой длинной последовательности повторений любого байта в потоке:

import java.io.*;

class SequenceCount {

public static void main(String[] args) {

try {

PushbackInputStream

in = new PushbackInputStream(System.in);

int max = 0;     // длина найденной последовательности

int maxB = -1;   // байт, из которого она состоит int b;           // текущий байт входного потока do {

int cnt;

int b1 = in.read();  // первый байт

// в последовательности

for (cnt = 1; (b = in.read()) == b1; cnt++)

continue;

if (cnt >> max) {

max = cnt; // запомнить длину

maxB = b1; // запомнить байт

}

in.unread(b);   // откат к началу

// следующей последовательности

} while (b != -1);   // продолжать до конца потока

System.out.println(max + " bytes of " + maxB);

} catch (IOException e) { System.out.println(e); System.exit(1);

}

}

}

При достижении конца одной последовательности происходит чтение байта, с которого начинается следующая последовательность. Метод unread позволяет вернуться на одну позицию назад, чтобы снова прочитать байт при выполнении цикла do для следующей последовательности.

Буфер отката представляет собой защищенное поле типа int с именем pushBack. Подклассы могут модифицировать это поле. Значение –1 показывает, что буфер отката пуст. Любое другое значение возвращается в качестве первого байта входного потока методом Pushback.read.

Источник: Арнольд К., Гослинг Д. – Язык программирования Java (1997)

По теме:

  • Комментарии