Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Laboratornaya_rabota_6.doc
Скачиваний:
10
Добавлен:
05.06.2015
Размер:
2.83 Mб
Скачать

Класс RandomAccessFile

Класс RandomAccessFile предоставляет более совершенный механизм для работы с файлами, чем файловые потоки. Он не является расширением Input Stream или OutputStream, поскольку может осуществлять любую из операций чтения/записи или оба действия сразу. Режим работы с файлом указывается в качестве параметра для различных конструкторов. Класс Random AccessFile реализует оба интерфейса Data InputStream и DataOutput Stream, поэтому он может применяться для чтения/записи встроенных типов Java.

Хотя класс RandomAccessFile не является расширением входных и выходных потоковых классов, имена и сигнатуры содержащихся в нем методов совпадают с вызовами read и write. Хотя это означает, что вам не придется учить новый набор имен и семантик для выполнения той же самой задачи, объекты класса RandomAccessFile не могут использоваться там, где требуется присутствие объектов InputStream или OutputStream. Тем не менее, вы можете использовать объекты RandomAccessFile вместо объектов-потоков DataInput или DataOutput.

Класс RandomAccessFile содержит три конструктора:

  • public RandomAccessFile(String name, String mode)

Создает объект RandomAccessFile для заданных имени файла и режима. Режим указывается в виде “r” или “rw” для доступа по чтению или чтению/записи соответственно. Любое другое значение режима приводит к возбуждению IOException.

  • public RandomAccessFile(File file, String mode)

Создает объект RandomAccessFile для заданного объекта класса File и режима.

  • public RandomAccessFile(FileDescriptor fd)

Создает объект RandomAccessFile для заданного объекта fd типа File Descriptor (см. раздел “Файловые потоки и FileDescriptor”).

Термин “произвольный доступ” (random access), вынесенный в название типа, обозначает возможность установки файлового указателя чтения/записи в любую позицию внутри файла с последующим выполнением нужной операции. Эта возможность обеспечивается следующими методами:

  • public long getFilePointer()

Возвращает текущее смещение (в байтах) от начала файла.

  • public void seek(long pos)

Устанавливает файловый указатель в заданную позицию (в байтах). Следующий считанный или записанный байт будет иметь смещение pos.

  • public long length() throws IOException

Возвращает длину файла.

Класс StreamTokenizer

Разделение входного потока на отдельные лексемы встречается довольно часто, поэтому пакет java.io содержит специальный класс StreamTokenizer для выполнения простейшего лексического анализа. В настоящее время этот класс в полной мере работает лишь с младшими 8 битами Unicode, составляющими подмножество символов Latin-1, поскольку внутренний массив класса, хранящий информацию о категориях символов, состоит только из 256 элементов. Символы, превышающие \u00ff, считаются алфавитными. Хотя в подавляющем большинстве случаев это действительно так (собственно, большая часть символов относится к алфавитным), вы, например, не сможете назначить в качестве ограничителя символ ‘?‘ (\u270D). Даже с учетом этого условия выделение лексем во многих случаях происходит нормально.

Чтобы выделить лексемы в потоке, следует создать объект StreamTokenizer на основе объекта InputStream и затем установить параметры анализа. Цикл сканирования вызывает метод nextToken, который возвращает тип следующей лексемы в потоке. С некоторыми типами лексем связываются значения, содержащиеся в полях объекта StreamTokenizer.

Когда метод nextToken распознает следующую лексему, он возвращает ее тип и присваивает это же значение полю ttype. Имеются четыре типа лексем:

  • TT_WORD: обнаружено слово. Найденное слово помещается в поле sval типа String.

  • TT_NUMBER: обнаружено число. Найденное число помещается в поле nval типа double. Распознаются только десятичные числа с плавающей точкой (с десятичной точкой или без нее). Анализатор не распознает 3.4e79 как число с плавающей точкой, или 0xffff как шестнадцатеричное число.

  • TT_EOL: обнаружен конец строки.

  • TT_EOF: обнаружен конец файла.

Символы входного потока делятся на специальные и ординарные. Специальными считаются символы, которые особым образом обрабатываются в процессе анализа, — пробелы, символы, образующие числа и слова, и так далее. Все остальные символы относятся к ординарным. Если следующий символ потока является ординарным, то тип лексемы совпадает с символом. Например, если в потоке встречается символ ‘В‘ и он не является специальным, то тип лексемы (и поле ttype) равен эквиваленту символа ‘В‘ в типе int.

Анализатор распознает несколько категорий символов, которые определяются следующими методами:

  • public void wordChars(int low, int hi)

Символы в этом диапазоне образуют слова; они могут входить в лексему типа TT_WORD. Допускается многократный вызов этого метода с разными диапазонами. Слово состоит из одного или нескольких символов, входящих в любой их допустимых диапазонов.

  • public void whitespaceChars(int low, int hi)

Символы в этом диапазоне являются разделителями. При анализе они игнорируются; их единственное назначение заключается в разделении лексем — например, двух последовательных слов. Как и в случае wordChars, можно вызывать этот метод несколько раз, при этом объединение всех диапазонов определяет набор символов-разделителей.

  • public void ordinaryChar (int ch)

Символ ch является ординарным. Ординарный символ при анализе потока возвращается сам по себе, а не в виде лексемы.

  • public void ordinaryChars (int low, int hi)

Символы в диапазоне являются ординарными.

  • public void commentChar (int ch)

Символ ch начинает однострочный комментарий — символы от ch до ближайшего конца строки считаются одним длинным разделителем.

  • public void quoteChar (int ch)

Пары символов ch являются ограничителями для строковых констант. Когда в потоке распознается строковая константа, символ ch возвращается в качестве лексемы, а поле sval содержит тело строки (без символов-ограничителей). При чтении строковых констант обрабатываются некоторые стандартные символы Java в записи с \ (например, \t), но не все. Строки, воспринимаемые StreamTokenizer, представляют собой подмножество строк Java. Особенно жесткий запрет накладывается на использование \xxxx, \’, \" или (к сожалению) \Q, где символ Q совпадает с символом-ограничителем ch. В потоке могут присутствовать несколько разных символов-ограничителей, но строки должны начинаться и заканчиваться одним и тем же ограничителем. Другими словами, строка, которая начинается одним символом-ограничителем, продолжается до следующего вхождения того же символа; если в середине строки встречается другой символ-ограничитель, то он просто считается частью строки.

  • public void parseNumbers()

Указывает на необходимость выделения чисел из потока. StreamTokenizer выдает числа с плавающей точкой двойной точности и возвращает тип лексемы TT_NUMBER, а значение лексемы помещается в поле nval. Просто отказаться от поиска чисел невозможно — для этого придется либо вызвать ordinaryChars для всех символов, входящих в состав числа (не забудьте о десятичной точке и знаке “минус”), либо вызвать resetSyntax.

  • public void resetSyntax()

Сбрасывает синтаксическую таблицу, в результате чего все символы становятся ординарными. Если вы вызовете resetSyntax и затем начнете читать поток, то nextToken всегда будет выдавать следующий символ потока, как будто вы используете метод InputStream.read.

Не существует методов для определения категории заданного символа или для добавления новых категорий. Ниже приведены значения параметров по умолчанию для только что созданного объекта StreamTokenizer:

  1. wordChars(‘a’, ‘z’);

  2. wordChars(‘A’, ‘Z’);

  3. wordChars(128 + 32, 255);

  4. whitespaceChars(0, ‘ ‘);

  5. commentChar(‘/’);

  6. quoteChar(‘"’);

  7. quoteChar(‘\’’);

  8. parseNumbers();

Остальные методы управляют поведением анализатора:

  • public void eolIsSignificant(boolean flag)

Если значение flag равно true, то конец строки является существенным, и nextToken может возвращать TT_EOL. В противном случае концы строк считаются символами-разделителями и TT_EOL никогда не возвращается. Значение по умолчанию равно false.

  • public void slashStarComments(boolean flag)

Если значение flag равно true, анализатор распознает комментарии вида /*...*/. Значение по умолчанию равно false.

  • public void slashSlashComments(boolean flag)

Если значение flag равно true, анализатор распознает комментарии от // до конца строки. Значение по умолчанию равно false.

  • public void lowerCaseMode(boolean flag)

Если значение flag равно true, все символы в лексемах типа TT_WORD преобразуются в нижний регистр, если имеется соответствующий эквивалент (то есть к слову применяется метод String.toLowerCase). Значение по умолчанию равно false.

Имеется также несколько методов общего назначения:

  • public void pushBack()

Заносит предыдущую лексему обратно в поток. Следующий вызов nextToken снова вернет ту же самую лексему. Глубина отката ограничивается одной лексемой; несколько последовательных вызовов pushBack эквивалентны одному вызову.

  • public int lineno()

Возвращает текущий номер строки. Обычно это бывает полезно для вывода сообщений о найденных ошибках.

  • public String toString()

Возвращает строковое представление последней возвращенной лексемы, включающее номер строки.

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]