Главная страница

Java. Полное руководство. 8-е издание. С. Н. Тригуб Перевод с английского и редакция


Скачать 25.04 Mb.
НазваниеС. Н. Тригуб Перевод с английского и редакция
АнкорJava. Полное руководство. 8-е издание.pdf
Дата28.02.2017
Размер25.04 Mb.
Формат файлаpdf
Имя файлаJava. Полное руководство. 8-е издание.pdf
ТипДокументы
#3236
страница57 из 90
1   ...   53   54   55   56   57   58   59   60   ...   90
throws IOException
final boolean readBoolean( )
throws IOException
final int readlnt(
)
throws В следующей программе демонстрируется использование классов
DataOutput­
Stream и
DatalnputStream.
Глава 19. Ввод-вывод: пакет java.io
6 2 1
// Демонстрация применения DatalnputStream и DataOutputStream.
// Эта программа использует оператор try-с-ресурсами. Требует JDK 7.
import java.io.*;
class DatalODemo {
public static void main(String a r g s [])
// Сначала запись данных
try (
DataOutputStream dout =
new DataOutputStream(new FileOutputStream("Test.da t ")) )
{
d o u t .writeDouble(98.6);
do u t .w r i telnt(
1000);
d o u t .writeBoolean(true);
} catch(FileNotFoundException e) {
System.out.println("Cannot Open Output File");
return;
} c a t c h (IOException e) {
System.out.println("I/O Error: " + e ) ;
}
// Теперь прочитать данные назад
try (
DatalnputStream din =
new DatalnputStream(new Filelnputstream("Test.d a t ")) )
{
double d = din.readDouble();
int i = d i n .readlnt();
boolean b = d i n Вот значения " +
'd + " " + i + " " + b) ;
} catch(FileNotFoundException e) {
System.out.println("Cannot Open Input File");
return;
} c a t c h (IOException e) {
System.out.println("I/O Error: " + e) Вывод приведен ниже.
Вот значения 98.6 1000 Класс R a n d o m A c c e s s F Класс R an d o m A ccessF ile инкапсулирует файл произвольного доступа. Он не наследуется от класса In p u tS tre a m или O utp u tStream . Вместо этого qh реализует интерфейсы Dat a In p u t и D ataO u tp u t, которые определяют базовые методы ввода-вывода. Он также реализует интерфейсы A u to C lo se a b le и C lo s e a b le . Класс R an d o m A ccessF ile отличает его поддержка запросов на позиционирование, те. вы можете установить указатель файла в любое место в пределах этого файла. Этот класс включает следующие два конструктора
объектФайла,
String доступ)
throws FileNotFoundException
RandomAccessFile(String
имяфайла,
String доступ)
throws Впервой форме объект Файла задает открываемый файл как объект класса
F i l e . Во второй форме имя файла передается параметром имя файла. В обоих

6 2 2 Часть II. Библиотека случаях доступ определяет тип доступа. Если он равен " г ", то файл может быть прочитан, ноне может быть записан. Если " r w " , то файл открывается в режиме чтения-записи. Если же доступ равен " r w s ", то файл открывается для операций чтения-записи и каждое изменение данных файла или его метаданных немедленно записывается на физическое устройство. Метод seek ()
, показанный ниже, используется для установки текущей позиции указателя внутри файла seek(long

новПоз)
throws Здесь новП оз указывает новую позицию в байтах файлового указателя от начала файла. После вызова метода seek
() следующая операция чтения или записи выполняется в этой новой позиции.
Класс
RandomAccessFile реализует стандартные методы ввода и вывода, которые вы можете использовать для чтения и записи файлов произвольного доступа. Кроме того, он включает несколько дополнительных методов. Одним из них является метод set
Length ()
. Его сигнатура такова setLength(long длина throws Этот метод устанавливает длину вызывающего файла равной указанному значению длина Метод может использоваться для удлинения или укорачивания файла. Если файл удлиняется, его добавочная порция является неопределенной.
Символьные потоки
В то время как классы байтовых потоков предоставляют необходимые функциональные возможности для выполнения операций ввода-вывода любого типа, они не могут работать напрямую с символами Unicode. Поскольку одной из главных целей Java является поддержка философии написано однажды, выполняется везде, понадобилось включить поддержку прямого ввода-вывода для символов. В этом разделе обсудим несколько классов символьного ввода-вывода. Как уже объяснялось, в вершине иерархии символьных потоков находятся абстрактные классы
Reader и
Writer. С них и начнем.
На заметку Как было сказано в главе 13, классы символьного ввода-вывода были добавлены в версии Java 1.1. По этой причине вы все еще можете встретить унаследованный код, использующий байтовые потоки там, где более целесообразно было бы применить символьные потоки. Работая с таким кодом, будет неплохо обновить его.
Класс
R e a d e Класс
Reader
— абстрактный класс, определяющий символьный потоковый ввод Java. Он реализует интерфейсы
AutoCloseable, Closeable и
Readable. Все методы этого класса (за исключением метода markSupported
( )) в случае ошибочных ситуаций передают исключение
IOException. В табл. 19.4 представлен краткий обзор методов класса Таблица 19.4. Методы, определенные в классе

R e a d e Метод Описание void close
() Закрывает входной поток. Последующие попытки чтения передадут исключение
IOException
void mark
(
int
количСимволов
)
Помещает метку в текущую позицию во входном потоке, которая остается корректной до тех пор, пока не будет прочитано количСимволов символов
Глава 19. Ввод-вывод: пакет java.io
6 2 Окончание табл. Описание m a r k S u p p o r t e d ()
int read()
int read(char буфер буфер буфер смещение коли ч Символов коли ч Символов Возвращает значение
true, если поток поддерживает методы
mark
() и
reset Возвращает целочисленное представление следующего доступного символа вызывающего входного потока. При достижении конца файла возвращает значение -Пытается прочитать доб уф ер символов в буфер biи возвращает количество успешно прочитанных символов. При достижении конца файла возвращает значение -Пытается читать символы в буфер и возвращает фактическое количество успешно прочитанных символов. При достижении конца файла возвращает значение -Пытается прочитать док о ли ч Символов biсимволов в буфер biначиная с буфер смещение возвращает количество успешно прочитанных символов. При достижении конца файла возвращает значение -Возвращает значение
true, если следующий запрос не будет ожидать. В противном случае возвращает значение Сбрасывает указатель ввода в ранее установленную позицию метки
Пропускает коли ч Символов biсимволов ввода, возвращая количество действительно пропущенных символов
Класс
W r i t e Класс
Writer
— абстрактный класс, определяющий символьный потоковый вывод. Реализует интерфейсы
AutoCloseable, Closeable, Flushable и
Appendable. В случае ошибок все методы этого класса передают исключение
IOException. Краткий обзор методов класса
Writer представлен в табл. Таблица 19.5. Методы, определенные в классе w rite Метод Описание riter append(char символ символы riter append(CharSequence
символы начало конец (Добавляет символ вконец вызывающего выходного потока. Возвращает ссылку на вызывающий поток
Добавляет символы вконец вызывающего выходного потока. Возвращает ссылку на вызывающий поток
Добавляет диапазон
символы,
заданный при помощи начало biи конец, вконец вызывающего выходного потока. Возвращает ссылку на вызывающий поток
Закрывает вызывающий поток. Последующие попытки записи передадут исключение
IOException

6 2 Часть II. Библиотека Метод void f l u s h ()
void write(int символ буфер буфер смещение коли ч Символов строка строка смещение коли ч Символ ов)

Описание______________________________ - -
Финализирует выходное состояние так, что все буферы очищаются. Иными словами, сбрасывает выходные буферы
Записывает единственный символ в вызывающий выходной поток. Обратите внимание на то, что параметр имеет тип
int, что позволяет вызывать метод
w r i t e
() с выражением без необходимости приведения обратно к типу
char. Однако записываются только младшие 16 бит
Записывает полный массив символов в вызывающий выходной поток
Записывает диапазон коли ч

С
и м волов iсимволов из массива буфер, начиная с буфер смещение, в вызывающий выходной поток
Записывает строка в вызывающий выходной поток
Записывает диапазон коли ч Символов biсимволов из строки строка начиная с указанного смещения смещение Окончание табл. Класс

F i l e R e a d e Это класс, производный от класса
Reader, который вы можете использовать для чтения содержимого файла. Два наиболее часто используемых его конструктора выглядят так

путькфайлу)
FileReader(File
объектФайла)
Оба могут передать исключение
FileNotFoundException. Здесь пут ькф айлу —
полное путевое имя файла, а объектФайла — объект класса
File, описывающий файл.
Следующий пример показывает, как можно читать строки из файла и печатать их в стандартный выходной поток. Он читает собственный исходный файл, который должен находиться в текущем каталоге Демонстрация применения FileReader.

// Эта программа использует оператор try-с-ресурсами. Требует JDK 7.
import java.io.*;
class FileReaderDemo {
public static void main(String a r g s []) {
try (
FileReader fr = new FileReader("FileReaderDemo.java")
)
{
int с ;
// Читает и отображает файл = fr.read(J) != -1) System.out.print((char) c ) ;
} c a t c h (IOException e) {
Глава 19. Ввод-вывод: пакет java.io
6 2 5
System.out.println("I/O Error: " + Класс
F i l e W r i t e Этот класс создает объект класса, производного от класса W r i t e r , который вы можете применять для записи файла. Рассмотрим его наиболее часто используемые конструкторы
путькфайлу)
FileWriter(String
путькфайлу,
boolean добавить
объектФайла)
FileWriter(File
объектФайла,
boolean
добавить)
Все они могут передавать исключение IO E x c e p tio n . Здесь пут ькф айлу — полное путевое имя файла, а объектФайла — объект класса F i l e , описывающий файл. Если добавить равно t r u e , то вывод добавляется вконец файла.
Создание объекта класса F i l e W r i t e r не зависит оттого, существует ли файл. Класс F i l e W r i t e r создаст файл перед его открытием для вывода, когда вы создаете объект. В случае попытки открытия файла, доступного только для чтения, передается исключение I O E x c e p tio n Следующий пример представляет собой версию символьного потока из примера, представленного ранее, когда речь шла о классе F i le O u tp u t S tr e a m . Эта версия создает простой буфер символов, сначала создавая объект класса S t r i n g , а затем используя метод g e t C h a rs () для извлечения эквивалентного символьного массива. Затем она создает три файла. Первый файл, f i l e . t x t , будет содержать каждый второй символ примера. Второй файл, f i l e 2 . t x t , будет хранить полный набор символов. И наконец, третий файл, f i 1еЗ . t x t , будет содержать только последнюю четверть символов Демонстрация применения FileWriter.
// Эта программа использует оператор try-с-ресурсами. Требует JDK 7.
import java.io.*;
class FileWriterDemo {
public static void main(String a r g s []) throws IOException {
String source = "Now is the time for all good men\n" +
" to come to the aid of their country\n" +
" and pay their due taxes.";
char bu f f e r [] = new char[source.length()];
source.getChars(0, source.length(), buffer, 0);
try (
FileWriter
fO = new FileWriter("filel.txt");
FileWriter fl = new FileWriter("file2.txt");
FileWriter f2 = new FileWriter("file3.txt") )
{
// запись в первый файл (int i=0; i < buffer.length; i += 2) {
f0 .write(buffer[i]);
}
// запись во второй файл
f1 .write(buffer);
// запись в третий файл
f2.write(buffer,buffer.length-buffer.length/4,buffer.length/4);

6 2 Часть II. Библиотека Java
} c a t c h (IOException e) {
S y s t e m . o u t . p r i n t l n ("An I/O Error Класс
C h a r A r r a y R e a d e Класс
CharArrayReader
— реализация входного потока, использующего символьный массив в качестве источника. Этот класс имеет два конструктора, каждый из которых принимает символьный массив в качестве источника данных массив массив начало

количСимволов)
Здесь массив входной источник. Второй конструктор создает объект класса, производного от класса
Reader, из подмножества символьного массива, начинающегося с символа в позиции, указанной параметром начало, и длиной коли чС им во лов.
Метод close
( ), реализованный классом
CharArrayReader, не передает исключений. Это связано стем, что он не может потерпеть неудачу.
В следующем примере используется пара объектов класса
CharArrayReader s.
// Демонстрация применения Эта программа использует оператор try-с-ресурсами. Требует JDK 7.
import java.io.*;
public class CharArrayReaderDemo {
public static void main(String a r g s []) {
String tmp = "abcdefghijklmnopqrstuvwxyz";
int length = t m p .length();
char c[] = new c h a r [length];
t m p .getChars(0, length,
c,
0) ;
int i ;
try (CharArrayReader inputl = new с ))
{
System.out.println("inputl:");
w h i l e ((i = inputl.r e a d ()) != -1) {
System.out.print((char)i );
}
System.out.println();
} cat c h (IOException e) {
System.out.println("I/O Error: " + e ) ;
}
try (CharArrayReader input2 = new с ,
0, 5))
{
System.out.println("input2:");
while((i = input2.r e a d ()) != -1) {
System.out.print((char)i) ;
}
System.out.println();
} c a t c h (IOException e) {
System.out.println("I/O Error: " + e ) ;
}
}
Глава 19. Ввод-вывод: пакет java.io
6 2 Объект input
1 создается из полного алфавита в нижнем регистре, в то время как объект input
2 содержит только первые пять букв. Вот вывод этой программы.
input1:
abcdefghijklmnopqrstuvwxyz
input2:
abcde
Класс
C h a r A r r a y W r i t e Класс
CharArrayWriter
— реализация выходного потока, использующего в качестве места назначения вывода массив. Класс
CharArrayWriter имеет два следующих конструктора

количСимволов)
В первой форме создается буфер с размером по умолчанию. Второй буфер создается с размером, заданным параметром количС им волов Буфер находится в поле buf класса
CharArrayWriter. Размер буфера будет при необходимости последовательно увеличиваться. Количество байтов, содержащихся в буфере, находится в поле count того же класса. Оба поля — buf и count
— являются защищенными. Метод close
() не имеет никакого влияния на класс В следующем примере демонстрируется использование класса
CharArrayWriter в переделанной программе, рассмотренной ранее, когда речь шла о классе
Byte­
ArrayOutputStream. Она приводит к тому же выводу, что и предыдущая версия Демонстрация применения CharArrayWriter.

// Эта программа использует оператор try-с-ресурсами. Требует JDK 7.
import java.io.*;
class CharArrayWriterDemo {
public static void main(String a r g s []) throws IOException {
CharArrayWriter f = new CharArrayWriter();
String s = "This should end up in the array";
char buf[] = new c h a r [s .length()];
s .
getChars (
0 ,
s.lengthO, buf, 0) ;
try {
f.write(buf);
} c a t c h (IOException e) {
System.out.println("Error Writing to Buffer");
return;
} Буфер в виде строки В массив с [] = f .toCharArray();

for (int i=0; i < c .length; i++) {
System.out.print(c[i]);
}
System.out.println("\nB FileWriter()");
// Использование Тгу-с-ресурсами для управления
// файловыми потоками (
FileWriter f2 = new FileWriter("test.t x t ") )

6 2 Часть II. Библиотека Java
{
f,writeTo(f2) ;
} c a t c h (IOException e) {
S y s t e m . o u t . p r i n t l n ("I/O Error: " + e ) ;
}
S y s t e m . o u t . p r i n t l n (Выполнение r e s e t ()");
f .r e s e t ();
for (int i=0; i<3; i++) f .w r i t e ('X ');
S y s t e m . o u t . p r i n t l n (f .t o S t r i n g (Класс Класс
Buf f e r e d R e a d e r увеличивает производительность за счет буферизации ввода. У него имеются два конструктора e a d e r ( R e a d e r

входнойПоток)
Buffere d R e a d e r ( R e a d e r
входнойПоток,
int
размерБуфера)
Первая форма создает буферизованный символьный поток, используя размер буфера по умолчанию. Во второй форме размер буфера задает
размерБуфера.
Закрытие объекта класса
Buf f e r e d R e a d e r приводит к закрытию также внутреннего потока, определенного аргументом входнойПот ок.
Как ив случае с байтовым потоком, буферизованный символьный входной поток также обеспечивает фундамент для поддержки перемещения обратно по потоку в пределах доступного буфера. Для обеспечения этого класс
Buf f e re d R e a d e r реализует методы mark () и r e s e t ( ) , а метод Buf f e r e d R e a d e r .m a rk S u p p o r t­
ed () возвращает значение tr u e Следующий пример представляет собой переработанную версию примера с классом
Buf f e r e d l n p u t S t r e a m , показанную выше, но использует символьный поток класса
Buf f e re d R e a d e r вместо буферизованного байтового потока. Как и ранее, он использует методы mark () и r e s e t () для разбора потока на предмет поиска конструкции HTML с символом авторских прав. Такая ссылка начинается с ампер­
санда (&) и заканчивается точкой с запятой ( ;) без внутренних пробелов. Пример ввода содержит два амперсанда, чтобы продемонстрировать случай, когда вызов метода r e s e t () происходит, а когда — нет. Вывод будет таким же, что и раньше Использование буферизованного ввода Этап рограмма использует оператор t r y -с-ресурсами. Требует JDK 7.

import java.io.*;
class BufferedRe a d e r D e m o {
public static void ma i n ( S t r i n g args[]) throws IOException {
String s = "This is a © copyright symbol " +
"but this is © not.\n";
char buf[] = n ew c h a r [s .l e n g t h ()];
s .g e t C h a r s (0, s.length(), buf, 0);
C h a r A r r ayReader in = n ew C h a r A r r a y R e a d e r ( b u f );
int с ;
b ool e a n mar k e d = false;
try (
B u fferedReader f = n ew B u f f e r e d R e a d e r (in) )
Глава 19. Ввод-вывод: пакет java.io
6 2 9
{
whil e (с = f . r e a d O ) != -1) {
switch(c) {
case '&':
if (Imarked) {
f.mark(32);
marked = true;
} else {
ma rk ed = false;
}
break;
case ';':
if (marked) {
m a r k e d = false;
System.out.print("(c)");
} else
System, out .print: ( (char) c) ;
break;
case 1
1:
if (marked) {
m a r k e d = false;
f .reset ();
S y s t e m . o u t . p r i n t ("&");
} else
S y s t e m . o u t . p r i n t ( (char) c ) ;
break;
d e f a u l t :
if ('marked)
S y s t e m . o u t . p r i n t ((char) c) ;
break;
}
}
} c a t c h (IOException e) {
S y s t e m . o u t . p r i n t l n ("I/O Error: " + e ) Класс Класс
Buf f e r e d W r ite r — это класс, производный от класса W riter, который буферизует вывод. Благодаря применению класса
Buf feredWr i t e r , можно повысить производительность за счет снижения количества операций физической записи в выходное устройство.
Класс
Buf f e r e d W r ite r имеет следующие два конструктора u f f e r e d W r iter(Writer

выходнойПоток)
B u f f e r e dWriter(Writer
выходнойПоток,
int
размерБуфера)
Первая форма создает буферизованный поток, использующий буфер с размером по умолчанию. Во второй размер буфера передается в параметре
размерБуфера.
Класс Класс
Push backR eader позволяет возвращать во входной поток один или более байтов. Это позволяет заглянуть во входной буфер. Вот два его конструктора u s hbackReader(Reader

входнойПоток)
P u s hbackReader(Reader
входнойПоток,
int
размерБуфера)

6 3 Часть II. Библиотека Первая форма создает буферизованный поток, позволяющий втолкнуть один символ. Во второй форме размер буфера вталкивания передается в параметре
размерБуфера.
При закрытии объекта класса
PushbackReader закрывается также внутренний поток, определенный аргументом
входнойПоток.
Класс
PushbackReader предоставляет метод unread ()
, который возвращает один или более символов в вызывающий входной поток. Доступны три формы этого метода unread(int символ throws IOException

void unread(char буфер буфер смещение int
количСимволов)
throws Первая форма вталкивает символ, переданный в параметре символ Этот символ будет первым, который затем вернет последующий вызов метода read (). Вторая форма возвращает в поток символы из буфер Третья форма вталкивает
количСимволов символов, начиная со смещения смещение, в буфер При попытке возврата символа в полный буфер передается исключение Следующая программа представляет собой переделанный пример с классом
PushbacklnputStream, в котором класс
PushbacklnputStream заменен классом
PushbackReader. Как и ранее, он показывает, как синтаксический анализатор языка программирования может использовать вталкивание в поток для обнаружения отличия между операциями сравнения (==) и присваивания (=).
// Демонстрация применения u n r e a d O .
// Эта программа использует оператор try-с-ресурсами. Требует JDK 7.
import java.io.*;
class PushbackReaderDemo {
public static void main(String a r g s []) {
String s = "if (a == 4) a = 0;\n";
char buf[] = new c h a r [s .length()];
s .
getChars (
0 ,
s.length(), buf, 0) ;
CharArrayReader in = new CharArrayReader(buf);
int с ;
try (
PushbackReader f = new PushbackReader(in) )
{
while (
(c = f.readO) != -1) {
switch(c) {
case '=':
if (
(c = f.readO )
== '
= '
)
System.o u t .p r i n t (".e q .");
else {
System.out.print("<-");
f .unread(c);
}
break;
default:
System.out.print((char) c ) ;
break;
}
} c a tch(IOException e) {
System.out.p r intln("I/O Error: " + e ) ;
}
Глава 19. Ввод-вывод: пакет java.io
6 3 Класс
P r i n t w r i t e Класс
Printwriter
— по сути, символьная версия класса
PrintStream. Он реализует интерфейсы
Appendable, Closeable и
Flushable. Класс
Printwriter имеет несколько конструкторов. Для начала рассмотрим следующие конструкторы

выходнойПоток)
Printwriter(OutputStream
выходнойПоток,
boolean
сбросПриНовойСтроке)
Printwriter(Writer
выходнойПоток)
Printwriter(Writer
выходнойПоток,
boolean
сбросПриНовойСтроке)
Здесь
выходнойПоток определяет открытый объект класса
OutputStream, который примет вывод. Параметр сбросПриНовойСтроке управляет автоматическим выталкиванием буфера при каждом вызове методов println
( )
,
printf
() или format ()
. Если параметр сбросПриНовойСтроке содержит значение true, то происходит автоматическое выталкивание буфера. Если же этот параметр содержит значение false, то автоматического выталкивания не происходит. Конструкторы, которые не принимают параметра сбросПриНовойСтроке, автоматического выталкивания не подразумевают.
Следующий набор конструкторов предоставляет простую возможность создания объекта класса
Printwriter, который пишет свой вывод в файл
выходнойФайл
)
throws FileNotFoundException
Printwriter(File
выходнойФайл,
String
наборсимволов)
throws FileNotFoundException, UnsupportedEncodingException
Printwriter(String
имяВыходногоФайла)
throws FileNotFoundException
Printwriter(String
имяВыходногоФайла,
String
наборсимволов)
throws FileNotFoundException, Они позволяют создать объект класса
Printwriter на основе объекта класса
File либо имени файла. В любом случае файл создается автоматически. Любой ранее существовавший файл стем же именем уничтожается. Будучи созданным, объект класса
Printwriter направляет весь вывод в указанный файл. Вы можете задать кодировку символов, передав ее имя в параметре
наборсимволов.
Класс
Printwriter предоставляет методы print
() и println
() для всех типов, включая тип
Object. Если аргумент не относится к элементарному типу, то методы класса
Printwriter вызывают метод toString
() такого объекта, аза тем выводят его результат.
Класс
Printwriter также поддерживает метод pr int f ()
. Он работает точно также, как ив классе
PrintStream, описанном ранее, — позволяя задать точный формат данных. Метод printf
() для класса
Printwriter объявлен следующим образом printf(String

формСтрока,
Object ... аргументы printf(Locale регион String
формСтрока,
Object ...
аргументы)
Первая версия пишет аргументы в стандартный вывод в формате, указанном в
формСтрока
, используя региональные данные по умолчанию. Вторая версия позволяет задать региональные данные. Обе возвращают вызывающий объект класса Метод format
() также поддерживается. Его общие формы таковы format(String
формСтрока,
Object ... аргументы format(Locale регион String
формСтрока,
Object ...
аргументы)
Этот метод работает подобно методу print f (Класс Ранее (в Java SE 6) был добавлен класс
Console. Он используется для чтения и записи информации на консоли, если таковая существует, и реализует интерфейс

6 3 Часть II. Библиотека Java
Flushable. Класс
Console, прежде всего, введен для удобства, поскольку большая часть его функциональных возможностей доступна через объекты
System, in и
System, out. Однако его применение позволяет упростить некоторые виды консольных итераций, особенно при чтении строк с консоли.
Класс
Console не поддерживает конструкторов. Его объект получают вызовом метода
System, console ().
static Если консоль доступна, возвращается ссылка на нее. В противном случае возвращается значение nul
1. Консоль не будет доступна во всех классах, поэтому если возвращается значение null, консольные операции ввода-вывода невозможны.
Класс
Console определяет методы, перечисленные в табл. 19.6. Обратите внимание на то, что методы ввода, такие как метод readLine ()
, передают исключение
IOException, когда возникают ошибки ввода. Класс исключения
IOError происходит от класса
Error и означает сбой ввода-вывода, который происходит вне контроля вашей программы. То есть обычно вы не будете перехватывать исключение
IOError. Откровенно говоря, если исключение
IOError возникнет в процессе обращения к консоли, обычно это свидетельствует о катастрофическом сбое системы.
Также обратите внимание на методы readPassword ()
, которые позволяют приложению считывать пароль, не отображая его на экране. Читая пароли, следует обнулять как массив, содержащий строку, введенную пользователем, таки массив, содержащий правильный пароль, с которым нужно сравнить первую строку. Это уменьшает шансы вредоносной программы получить пароль при помощи сканирования памяти.
Таблица 19.6. Методы, определенные в классе
C o n s o l e Метод Описание

.
' , - >
4
,-4 44 -
v oid f l u s h ()
Console f o r m a t (String форм Строка аргументы )
Console p r i n t f (String форм Строка аргументы )
Reader r e a d e r ()
String r e a d L i n e ()
String readLine(String форм Строка аргументы )
c h a r [ ] r e a d P a s s w o r d (Выполняет физическую запись буферизованного вывода на консоль
Выводит на консоль аргументы используя формат, указанный в формСтрока
Выводит на консоль аргументы,
используя формат, указанный в формСтрока
Возвращает ссылку на объект класса, производного от класса
Reader, соединенный с консолью Читает и возвращает строку, введенную с клавиатуры. Ввод прекращается нажатием клавиши . Если достигнут конец входного потока консоли, возвращается значение
null. В случае сбоя передается исключение Отображает строку приглашения, форматированную в соответствии с

формСтрока и
аргументы,
затем читает и возвращает строку, введенную с клавиатуры. Ввод прекращается, когда пользователь нажимает клавишу . Если достигнут конец входного потока консоли, возвращается значение
null. В случае сбоя передается исключение Читает и возвращает строку, введенную с клавиатуры.
Ввод прекращается нажатием клавиши . При этом строка не отображается. Если достигнут конец входного потока консоли, возвращается значение
null. В случае сбоя передается исключение
IOError__________________
Глава 19. Ввод-вывод: пакет java.io
6 3 Окончание табл. Описание h a r [ ]
r e a d P a s s w o r d (S t r i n g
формСтрока,
O b j e c t . . . аргументы r i n t w r i t e r w r i t e r (Отображает строку приглашения, форматированную в соответствии с
формСтрока
и аргументы, а затем читает и возвращает строку, введенную с клавиатуры. Ввод прекращается, когда пользователь нажимает клавишу . При этом строка не отображается. Если достигнут конец входного потока консоли, возвращается значение В случае сбоя передается исключение
I O E r r o r Возвращает ссылку на объект класса, производного от класса
Writer, ассоциированный с консолью
Рассмотрим пример, демонстрирующий класс C o n s o le в действии Демонстрация применения g a r g s []) {

String str;
Console con;
// Получить ссылку на консоль
con = S y s t e m . c o n s o l e ();
// Если нет доступной консоли, выход
if(con == null) return;
// Прочесть строку и отобразить ее
str
=
c o n Введите строку "Вот ваша строка
%s\n",
Вывод этого примера.
Введите строку Это тест.
Вот ваша строка Это тест.
Сериализация
Сериализация — это процесс записи состояния объекта в байтовый поток. Она удобна, когда нужно сохранить состояние вашей программы в области постоянного хранения, такой как файл. Позднее вы можете восстановить эти объекты, используя процесс десериализации.
Сериализация также необходима в реализации дистанционного вызова методов
(Remote M ethod Invocation — RMI). RMI позволяет объекту Java на одной машине обращаться к методу объекта Java на другой машине. Объект может быть применен как аргумент этого дистанционного метода. Посылающая машина сериализу­
ет объект и передает его. Принимающая машина десериализует его. (Подробнее о RMI будет рассказано в главе Предположим, что объект, подлежащий сериализации, ссылается на другие объекты, которые, в свою очередь, имеют ссылки на еще какие-то объекты. Такой набор объектов и отношений между ними формирует ориентированный граф. В этом графе могут присутствовать и циклические ссылки. Иными словами, объект X может содержать ссылку на объекта объект Y — обратную ссылку на X. Объекты также

6 3 Часть II. Библиотека могут содержать ссылки на самих себя. Средства сериализации и десериализации объектов устроены так, что могут корректно работать во всех этих сценариях. Если вы попытаетесь сериализовать объект, находящийся на вершине такого графа объектов, то все прочие объекты, на которые имеются ссылки, также будут рекурсивно найдены и сериализованы. Аналогично вовремя процесса десериализации все эти объекты и их ссылки корректно восстанавливаются.
Ниже приведен обзор интерфейсов и классов, поддерживающих сериализацию.
Интерфейс
S e r i a l i z a b l Только объект, реализующий интерфейс
S e r i a l i z a b l e , может быть сохранен и восстановлен средствами сериализации. Интерфейс не содержит никаких членов. Он просто используется для того, чтобы указать, что класс может быть сериализован. Если класс является сериализуемым, все его подклассы также сериализуемы.
Переменные, объявленные как t r a n s i e n t , не сохраняются средствами сериа­
лизации. Не сохраняются также статические переменные.
Интерфейс
E x t e r n a l i z a b l Средства Java для сериализации и десериализации спроектированы так, что большая часть работы по сохранению и восстановлению состояния объекта выполняется автоматически. Однако бывают случаи, когда программисту нужно управлять этим процессом. Например, может оказаться желательным использовать технологии сжатия и шифрования. Интерфейс предназначен именно для таких ситуаций.
И нтерфейс
E x t e r n a l i z a b l e определяет следующие два метода readExternal(Objectlnput

входнойПоток)
throws IOException, ClassNotFoundException
void writeExternal(ObjectOutput
выходнойПоток)
throws В этих методах
входнойПоток
это байтовый поток, из которого объект может быть прочитана
выходнойПоток
— байтовый поток, куда он записывается.
Интерфейс
O b j e c t O u t p u Интерфейс
Obj e c t O u t p u t расширяет интерфейсы
A u t o C l o s e a b l e и
D a ta -
O u t p i t , поддерживает сериализацию объектов. Он определяет методы, показанные в табл. 19.7. Особо отметим метод w r i t e O b j e c t
(). Он вызывается для сериализа­
ции объекта. В случае ошибок все методы этого интерфейса передают исключение O E x c e p tio n Таблица 19.7. Методы, определенные в интерфейсе

o b j e c t O u t p u t
Метод
Описание
void c l o s e (Закрывает вызывающий поток. Последующие попытки записи передадут исключение f l u s h ()
Финализирует выходное состояние, чтобы очистить все буферы. То есть все выходные буферы сбрасываются
Глава 19. Ввод-вывод: naxeTjava.io
6 3 Окончание табл. Описание write (byte буфер write (byte буфер смещение
колБайтов)
void write(int
b)
void writeObject(Object объект)
Записывает массив байтов в вызывающий поток Записывает диапазон колБайтов байт из массива буфер начиная с буфер [ смещение]
Записывает одиночный байт в вызывающий поток. Из аргумента Ь записывается только младший байт
Записывает объект объект в вызывающий поток
Класс
O b j e c t O u t p u t S t r e a Класс
Obj e c t O u t p u t S t r e a m расширяет класс
O u t p u t S t r e a m и реализует интерфейс
O b j e c t O u t p u t . Этот класс отвечает за запись объекта в поток. Конструктор его выглядит так

выходнойПоток)
throws Аргумент выходнойПоток
представляет собой выходной поток, в который могут быть записаны сериализуемые объекты. Закрытие объекта класса
Obj e c t ­
O u tp u tS tr e a m приводит к закрытию также внутреннего потока, определенного аргументом выходнойПоток.
Несколько часто используемых методов класса перечислено в табл. 19.8. В случае ошибки все они передают исключение
IO E x c e p t io n . Присутствует также класс
P u t F i e l d , вложенный в класс
Obj e c tO u tp u t S t r e a m . Он обслуживает запись постоянных полей, и описание его применения выходит за рамки настоящей книги.
Таблица 19.8. Некоторые из наиболее часто используемых методов класса
O b j e c t O u t p u t S t r e a Г' У V"
Метод
Описание
void c l o s e ()
void f l u s h ()
void write (byte буфер буфер смещение
колБайтов)
void write(int
b)
void writeBoolean(boolean
b)
void w r i t e B y t e (int
b)
void w r i t e B y t e s (String строка w r i t e C h a r (int Закрывает вызывающий поток. Последующие попытки записи передадут исключение
IOException. Внутренний поток тоже закрывается
Финализирует выходное состояние, так что все буферы очищаются. То есть все выходные буферы сбрасываются
Записывает массив байтов в вызывающий поток
Записывает диапазон колБайтов байт из массива буфер начиная с буфер [ смещение]
Записывает одиночный байт в вызывающий поток. Из аргумента
b
записывается только младший байт
Записывает значение типа
boolean в вызывающий поток
Записывает значение типа
byte в вызывающий поток. Записываемый байт — младший из аргумента Ь
Записывает байты, составляющие строку
str, в вызывающий поток
Записывает значение типа
char в вызывающий поток

6 3 6 Часть II. Библиотека Окончание табл. 19.8
«I
Лг
’ г »%'-f •*- й
<•***«*
1,4>г #«*£»■ Ц - « ’"■£*
void w r i t e C h a r s (String строка writeDouble(double d)

void w r i t e F l o a t (float
f)
void writelnt(int i)
void writeLong(long
1)
final void writeObject(Object объект Записывает символы, составляющие строку строка, в вызывающий поток
Записывает значение типа
double в вызывающий поток
Записывает значение типа
float в вызывающий поток
Записывает значение типа
int в вызывающий поток
Записывает значение типа
long в вызывающий поток
Записывает объект объект в вызывающий поток
Записывает значение типа
short в вызывающий поток
Интерфейс
Obj
ect Интерфейс расширяет интерфейсы
AutoCloseable и
Data­
lnput и определяет методы, перечисленные в табл. 19.9. Он поддерживает сериа­
лизацию объектов. Особо стоит отметить метод readObject
(). Он вызывается для десериализации объекта. В случае ошибок все эти методы передают исключение
IOException. Метод readObject
() также может передать исключение Таблица

1 9 .9 . Методы, определенные в интерфейсе
o b j e c t l n p u t
Меток
О яи и й ие
int a v a i l a b l e ()
void c l o s e ()
int read()
int read(byte буфер read(byte буфер смещение
колБайтов)
Obj ect readObj e c t ()
Long skip(long Возвращает количество байтов, которые доступны во входном буфере в настоящий момент
Закрывает вызывающий поток. Последующие попытки чтения вызовут передачу исключения
IOException. Внутренний поток тоже закрывается
Возвращает целочисленное представление следующего доступного байта ввода. При достижении конца файла возвращается значение -Пытается прочитать доб уф ер длина байт в буфер
,
начиная с буфер [ смещение, возвращая количество байтов, которые удалось прочитать. При достижении конца файла возвращается значение -Пытается прочитать до кол Байтов байт в буфер начиная с буфер [ смещение, возвращая количество байтов, которые удалось прочитать. При достижении конца файла возвращается значение -Читает объект из вызывающего потока
Игнорирует (те. пропускает) колБайтов байт вызывающего потока, возвращая количество действительно пропущенных байтов
Глава 19. Ввод-вывод: пакет java.io
6 3 Класс
O b j e c t I n p u t S t r e a Этот класс расширяет класс
I при t
S t г е аш и реализует интерфейсе с
11 при Класс
Obj ect
Input
Stream отвечает зачтение объектов из потока. Ниже показан конструктор этого класса

входнойПоток)
throws Аргумент входнойП от ок — это входной поток, из которого должен быть прочитан сериализованный объект. Закрытие объекта класса
Obj ect
Input
Stream приводит к закрытию также внутреннего потока, определенного аргументом
входнойПоток.
Несколько часто используемых методов этого класса показано в табл. 19.10. В случае ошибок все они передают исключение
IOException. Метод readOb- ject() также может передать исключение
ClassNotFoundException. Также в классе
Obj ect
InputStream присутствует вложенный класс по имени
GetField. Он обслуживает чтение постоянных полей, и описание его применения выходит за рамки настоящей книги.
Таблица 19.10. Часто используемые методы, определенные в классе
ObjectlnputStream
Метод
Описание
int a v a i l a b l e ()
v oid c l o s e ()
int read()
int read(byte буфер смещение
колБайтов)
Boolean r e a d B o o l e a n ()
byte r e a d B y t e ()
char r e a d C h a r ()
double r e a d D o u b l e ()
double r e a d F l o a t ()
void readFully(byte буфер буфер смещение кол Байтов)
Возвращает количество байтов, доступных в данный момент во входном буфере
Закрывает вызывающий поток. Последующие попытки чтения вызовут передачу исключения
IOException. Внутренний поток тоже закрывается
Возвращает целочисленное представление следующего доступного байта ввода. При достижении конца файла возвращается значение -Пытается прочитать до кол Байтов байт в буфер b,bначиная с буфер [ смещение, возвращая количество байтов, которые удалось прочитать. При достижении конца файла возвращается значение -Читает и возвращает значение типа
boolean из вызывающего потока
Читает и возвращает значение типа
byte из вызывающего потока
Читает и возвращает значение типа
char из вызывающего потока
Читает и возвращает значение типа
double из вызывающего потока
Читает и возвращает значение типа
float из вызывающего потока
Читает буфер. длина байт в буфер.
Возвращает управление, только когда все байты прочитаны
Читает колБайтов байт в буфер, начиная с буфер [ смещение]
Возвращает управление, только когда прочитано кол Байтов байт

6 3 Часть II. Библиотека Окончание табл. 19.10

Метод
Описание
int r e a d l n t (Читает и возвращает значение типа
int из вызывающего потока r e a d L o n g (Читает и возвращает значение типа
long из вызывающего потока Object Читает и возвращает объект из вызывающего потока r e a d S h o r t (Читает и возвращает значение типа
short из вызывающего потока r e a d U n s i g n e d B y t e (Читает и возвращает значение типа
unsigned
byte из вызывающего потока r e a d U n s i g n e d S h o r t (Читает и возвращает значение типа
unsigned
short из вызывающего потока
Пример сериализации
В следующей программе показано, как использовать сериализацию и десериа­
лизацию объектов. Начинается она с создания экземпляра объекта
MyClass. Этот объект имеет три переменные экземпляра типа
String, int и double. Именно эту информацию мы хотим сохранять и восстанавливать.
В программе создается объект класса
FileOutputStream, который ссылается на файл по имении для этого файлового потока создается объект класса
Obj ectOutputStream. Метод writeObject
() этого объекта класса
Obj ect­
OutputStream используется затем для сериализации объекта. Объект выходного потока очищается и закрывается.
Далее создается объект класса
Filelnputstream, который ссылается на файл по имении для этого файлового потока создается объект класса
Obj ect
InputStream. Метод readObj ect
() класса
Obj ect
Input
St ream используется для последующей десериализации объекта. После этого входной поток за­
крывается.
О братите внимание на то, что объект
MyClass определен с реализацией интерфейса. Если бы этого не было, передалось бы исключение
NotSerializableException. Поэкспериментируйте с этой программой, объявляя некоторые переменные экземпляра
MyClass как transient. Эти данные не будут сохраняться при сериализации.
// Демонстрация сериализации
// Эта программа использует оператор try-с-ресурсами. Требует JDK 7.
import java.io.*;
public class SerializationDemo {
public static void main(String a r g s []) {
// Сериализация объекта (
ObjectOutputStream objOStrm =
new ObjectOutputStream(new FileOutputStream("serial")) )
{
MyClass objectl = new M y C l a s s ("Hello", -7, 2.7el0);
System.out.println("objectl:
" + objectl);
objOStrm.writeObject(objectl);
Глава 19. Ввод-вывод: пакете) Исключение вовремя сериализации :
" + е) ;
}
// Десериализация объекта (
ObjectlnputStream objIStrm =
new ObjectlnputStream(new Filelnputstream("serial")) )
{
MyClass object2 = (MyClass)objIStrm.readObject();
System.out.println("object2:
" + object2);
}
catch(Exception e) {
System-, o u t .println (Исключение вовремя сериализации: " + е) ;
System.exit(0) ;
}
}
}
class MyClass implements Serializable {
String s;
int i;
double d;
public M y Class(String s, int i, double d) {
this.s = s;
this.i = i;
this.d = d;
}
public String toString() {
return "s=" + s +
i=" + i +
d=" + Эта программа демонстрирует идентичность переменных экземпляра объектов o b j e c t l и o b j e c t
2. Вот ее вывод s=Hello; i=-7; d=2.7ElO

object2: s=Hello; i=-7; Преимущества потоков
Потоковый интерфейс ввода-вывода в Java предоставляет чистую абстракцию для сложных и зачастую обременительных задач. Композиция классов фильтрующих потоков позволяет динамически строить собственные настраиваемые потоковые интерфейсы, которые отвечают вашим требованиям к передаче данных. Программы Java, использующие эти абстрактные высокоуровневые классы —
I n p u t S t r e a m , O u tp u tS tr e a m , R e a d e r и
W r i t e r ,
— будут корректно функционировать в будущем, даже когда появятся новые усовершенствованные конкретные потоковые классы. Как вы увидите в главе 21, эта модель работает очень хорошо, когда мы переключаемся от набора потоков на основе файлов к сетевым потоками потокам сокетов. И наконец, сериализация объектов играет важную роль в программах Java различных типов. Классы сериализации ввода-вывода Java обеспечивают переносимое решение этой непростой задачи



1   ...   53   54   55   56   57   58   59   60   ...   90


написать администратору сайта