Кен Арнольд Джеймс Гослинг

Вид материалаДокументы

Содержание


11.16. Потоки данных
11.16.1. Классы потоков данных
Подобный материал:
1   ...   55   56   57   58   59   60   61   62   ...   81

11.16. Потоки данных


Хотя возможность чтения и записи байтовых потоков достаточно полезна, часто бывает необходимо пересылать в потоке данные определенного типа. Интерфейсы DataInput и DataOutput определяют методы для пересылки примитивных типов Java в потоке. Реализация этих интерфейсов по умолчанию представлена классами D ataInputStream и DataOutputStream. Сначала мы рассмотрим интерфейсы, а затем их реализации.

Интерфейсы для входных и выходных потоков данных являются практически зеркальными отражениями друг друга. В приведенной ниже таблице содержатся параллельные методы чтения и записи для каждого из типов:

Read

Write

Тип

readBoolean

writeBoolean

boolean

readChar

writeChar

char

readByte

writeByte

byte

readShort

writeShort

short

readInt

writeInt

int

readLong

writeLong

long

readFloat

writeFloat

float

readDouble

writeDouble

double

readUTF

writeUTF

String в формате UTF

UTF является сокращением от “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.