К. Арнольд, Д. Гослинг - Язык программирования Java (1160779), страница 46
Текст из файла (страница 46)
Примените все операторы к именованным величинам, а в конце работы программывыведите все три значения. Усложним задание — воспользуйтесь классом Hashtable, который применялся при разработке AttributedImpl, чтобыможно было работать с произвольным количеством именованных величин, не обязательно тремя.11.16. Потоки данныхХотя возможность чтения и записи байтовых потоков достаточно полезна, часто бывает необходимо пересылать в потоке данные определенноготипа.
Интерфейсы DataInput и DataOutput определяют методы для пересылки примитивных типов Java в потоке. Реализация этих интерфейсов поумолчанию представлена классами D ataInputStream и DataOutputStream. Сначала мы рассмотрим интерфейсы, а затем их реализации.Интерфейсы для входных и выходных потоков данных являются практически зеркальными отражениями друг друга. В приведенной нижетаблице содержатся параллельные методы чтения и записи для каждого из типов:ReadWriteТипreadBooleanwriteBooleanbooleanreadCharwriteCharcharreadBytewriteBytebytereadShortwriteShortshortreadIntwriteIntintreadLongwriteLonglongreadFloatwriteFloatfloatreadDoublewriteDoubledoublereadUTFwriteUTFString в форматеUTFUTF является сокращением от “Unicode Transmission Format” — символы Unicode переводятся в Unicode-1-1-UTF-8, компактную двоичную форму,спроектированную для кодировки 16-разрядных символов Unicode в 8-разрядных байтах.Кроме этих парных методов, DataInput содержит несколько своих собственных:public abstract void readFully(byte[] buf) throws IOExceptionЧитает последовательность байтов в buf, блокируя работу программы до завершения чтения.public abstract void readFully(byte[] b, int off, int len) •• throws IOExceptionЧитает последовательность байтов в buf, начиная с позиции offset, в количестве len байтов, если не встретится конец массива buf.
Работапрограммы блокируется до завершения чтения всех байтов.public abstract int skipBytes(int n) throws IOExceptionПропускает байты в потоке. Работа программы блокируется до пропуска всех n байтов.public abstract String readLine() throws IOExceptionЧитает строку вплоть до нахождения символов \n, \r или пары \r\n. Символы, завершающие строку, не включаются в нее. При достижении концавходного потока возвращается null.public abstract int readUnsignedByte() throws IOExceptionЧитает 8-разрядный байт без знака и возвращает его в виде значения типа in t.public abstract int readUnsignedShort() throws IOExceptionЧитает 16-разрядное целое типа short без знака и возвращает его в виде значения типа int, что дает число в диапазоне 0–65535 (2 16–1).Интерфейс DataInput обрабатывает встреченный конец файла, возбуждая исключение EOFException.
Класс EOFException является расширениемIOException.Интерфейс DataOutput содержит методы, сигнатуры которых совпадают с сигнатурами трех разновидностей метода write класса OutputStream, ив дополнение к ним поддерживает еще три метода:public abstract void writeBytes(String s) throws IOExceptionЗаписывает строку в виде последовательности байтов. Старший байт каждого символа при этом теряется, так что данный метод следуетприменять только для строк, содержащих символы в диапазоне от \u0000 до \u00ff, если только вы не готовы смириться с потерей данных.public abstract void writeChars(String s) throws IOExceptionЗаписывает строку в виде последовательности значений типа char.Чтение строк, записанных этими методами, должно осуществляться циклическим вызовом метода readChar, поскольку не существует методаreadBytes или readChars, возвращающего то же количество символов, которое было записано методом writeBytes или writeChars.
Вам придетсясначала записать длину строки или воспользоваться специальным символом-маркером, отмечающим ее конец. В первом случае можновоспользоваться методом readFully, чтобы считать полный массив байтов, однако с writeChars это уже не сработает, так как вам нужны значениятипа char, а не byte.11.16.1. Классы потоков данныхДля каждого интерфейса Data имеется соответствующий поток. Кроме того, класс RandomAccessFile реализует оба интерфейса для входных ивыходных потоков данных (см.
раздел “Класс RandomAccessFile”). Каждый из классов Data представляет собой расширение класса Filter, так чтопотоки данных могут использоваться для фильтрации других потоков. Следовательно, каждый из них должен иметь конструкторы, которыеполучают в качестве параметра другой входной или выходной поток. Например, фильтрация может применяться при записи данных в файл —для этого следует создать объект DataOutputStream до объекта FileOutputStream, а затем, при считывании данных из файла, поместитьDataInputStream перед объектом FileInput Stream.Упражнение 11.7Включите в класс Body из главы 2 метод, который записывает содержимое объекта в DataOutputStream, и конструктор, который считываетсостояние объекта из DataInputStream.11.17.
Класс 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) throws •• IOExceptionСоздает объект RandomAccessFile для заданных имени файла и режима. Режим указывается в виде “r” или “rw” для доступа по чтению или чтению/записи соответственно.
Любое другое значение режима приводит к возбуждению I OException.public RandomAccessFile(File file, String mode) throws •• IOExceptionСоздает объект RandomAccessFile для заданного объекта класса File и режима.public RandomAccessFile(FileDescriptor fd) throws IOExceptionСоздает объект RandomAccessFile для заданного объекта fd типа File Descriptor (см. раздел “Файловые потоки и FileDescriptor”).Термин “произвольный доступ” (random access), вынесенный в название типа, обозначает возможность установки файлового указателя чтения/записи в любую позицию внутри файла с последующим выполнением нужной операции.
Эта возможность обеспечивается следующими методами:public long getFilePointer() throws IOExceptionВозвращает текущее смещение (в байтах) от начала файла.public void seek(long pos) throws IOExceptionУстанавливает файловый указатель в заданную позицию (в байтах). Следующий считанный или записанный байт будет иметь смещение pos.public long length() throws IOExceptionВозвращает длину файла.Упражнение 11.8Напишите программу для чтения файла, который состоит из отдельных элементов, разделяемых строками, начинающимися с символов %%.Программа должна создавать сводный файл, содержащий начальную позицию для каждого такого элемента.
Затем напишите программу, котораяпечатает случайный элемент на основании сводного файла (см. описание метода Math.random в разделе “Класс Math”).11.18. Класс FileКласс File содержит стандартные средства для работы с именами файлов. Его методы позволяют разделять полные имена, включающие путь, насоставные части и запрашивать у файловой системы информацию о файлах.Объект File обычно связан с полным именем файла, причем необязательно существующего. Например, чтобы выяснить, представляет линекоторое имя существующий в системе файл, следует сначала создать объект File для данного имени, после чего вызвать для этого объектаметод exists.Полное имя /В этом разделе следует отличать полное имя файла от имени объекта класса файл. - Примеч. перев./ делится на две части: однаопределяет каталог (или папку), а другая — собственно файл.
Для разделения компонентов пути служит символ, хранящийся как значение типаchar в статическом поле separatorChar или значение типа String в статическом поле separator. Последнее вхождение этого символа в путьотделяет каталог от имени файла.Объекты File создаются одним из трех конструкторов:public File(String path)Создает объект File для работы с заданным файлом path.