Если в классе объявлены такие методы, то при сериализации объекта для записи его состояния будет вызван writeObject, который должен сгенерировать последовательность байт и записать ее в поток out, полученный в качестве аргумента. При этом можно вызвать стандартный механизм записи объекта путем вызова метода

out.defaultWriteObject();

Этот метод запишет все не- transient и не- static поля в поток данных.

В свою очередь, при десериализации метод readObject должен считать данные из потока in (также полученного в качестве аргумента) и восстановить значения полей класса. При реализации этого метода можно обратиться к стандартному механизму с помощью метода:

in.defaultReadObject();

Этот метод считывает описание объекта из потока и присваивает значения соответствующих полей в текущем объекте.

Если же процедура сериализации в корне отличается от стандартной, то для таких классов предназначен альтернативный интерфейс java.io.Externalizable.

При использовании этого интерфейса в поток автоматически записывается только идентификация класса. Сохранить и восстановить всю информацию о состоянии экземпляра должен сам класс. Для этого в нем должны быть объявлены методы writeExternal() и readExternal() интерфейса Externalizable. Эти методы должны обеспечить сохранение состояния, описываемого полями самого класса и его суперкласса.

При восстановлении Externalizable -объекта экземпляр создается путем вызова конструктора без аргументов, после чего вызывается метод readExternal.

Метод writeExternal имеет сигнатуру:

void writeExternal(ObjectOutput out) throws IOException;

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

void readExternal(ObjectInput in) throws IOException,ClassNotFoundException;

эти значения должны быть считаны в том же самом порядке.

Классы Reader и Writer и их наследники

Рассмотренные классы – наследники InputStream и OutputStream – работают с байтовыми данными. Если с их помощью записывать или считывать текст, то сначала необходимо сопоставить каждому символу его числовой код. Такое соответствие называется кодировкой.

Известно, что Java использует кодировку Unicode, в которой символы представляются двухбайтовым кодом. Байтовые потоки зачастую работают с текстом упрощенно – они просто отбрасывают старший байт каждого символа. В реальных же приложениях могут использовать различные кодировки (даже для русского языка их существует несколько). Поэтому в версии Java 1.1 появился дополнительный набор классов, основывающийся на типах Reader и Writer. Их иерархия представлена на рис. 15.2.

Эта иерархия очень схожа с аналогичной для байтовых потоков InputStream и OutputStream. Главное отличие между ними – Reader и Writer работают с потоком символов ( char ). Только чтение массива символов в Reader описывается методом read(char[]), а запись в Writer – write(char[]).

В таблице 15.1 приведены соответствия классов для байтовых и символьных потоков.

Рис. 15.2.

Иерархия классов Reader и Writer.

Таблица 15.1. Соответствие классов для байтовых и символьных потоков.Байтовый потокСимвольный потокInputStreamReaderOutputStreamWriterByteArrayInputStreamCharArrayReaderByteArrayOutputStr eam CharArrayWriter Нет аналогаInputStreamReaderНет аналогаOutputStreamWriterFileInputStreamFileReaderFileOutputStreamFileWriterFilterInputStreamFilterReader FilterOutputStreamFilterWriterBufferedInputStreamBufferedReaderBufferedOutputStreamBufferedWriterPrintStrea mPrintWriterDataInputStreamНет аналогаDataOutputStreamНет аналогаObjectInputStream Нет аналогаObjectOutputStreamНет аналогаPipedInputStreamPipedReaderPipedOutputStreamPipedWriterStringBufferInputStreamStringReaderНет аналогаStringWriterLineNumberInputStreamLineNumberReaderPushBackInputStreamPushBackReaderSequenceInp utStreamНет аналога

Как видно из таблицы, различия крайне незначительны и предсказуемы.

Например, конечно же, отсутствует преобразование в символьное представление примитивных типов Java и объектов ( DataInput/Output, ObjectInput/Output ). Добавлены классы-мосты, преобразующие символьные потоки в байтовые: InputStreamReader и OutputStreamWriter. Именно на их основе реализованы FileReader и FileWriter. Метод available() класса InputStream в классе Reader отсутствует, он заменен методом ready(), возвращающим булевое значение, – готов ли поток к считыванию (то есть будет ли считывание произведено без блокирования).

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

String fileName = 'd:\file.txt'; //Строка, которая будет записана в файл String data = 'Some data to be written and read. '; try{ FileWriter fw = new FileWriter(fileName); BufferedWriter bw = new BufferedWriter(fw); System.out.println('Write some data to file: ' + fileName); // Несколько раз записать строку for(int i=(int)(Math.random()*10);--i>=0;) bw.write(data); bw.close(); // Считываем результат FileReader fr = new FileReader(fileName); BufferedReader br = new BufferedReader(fr); String s = null; int count = 0;

Добавить отзыв
ВСЕ ОТЗЫВЫ О КНИГЕ В ИЗБРАННОЕ

0

Вы можете отметить интересные вам фрагменты текста, которые будут доступны по уникальной ссылке в адресной строке браузера.

Отметить Добавить цитату