Progress-servis55.ru

Новости из мира ПК
0 просмотров
Рейтинг статьи
1 звезда2 звезды3 звезды4 звезды5 звезд
Загрузка...

Java reader class

Потоки Reader и Writer

Абстрактные классы Reader и Writer являются символьными потоками.

Абстрактный класс Reader

Класс Reader обеспечивает поддержку символьного потока чтения аналогично тому, как это делает InputStream, реализующий модель байтового потока ввода. Методы Reader схожи с теми, которые объявлены в составе InputStream.

Методы класса Reader

МетодОписание
abstract void close() throws IOExceptionЗакрытие ранее открытого потока чтения. Метод используется для высвобождения ресурсов, связанных с потоком (таких как дескрипторы открытых файлов). Любые попытки обращения к закрытому потоку приводят к выбрасыванию исключения типа IOException, но повторное закрытие потока эффектов не вызывает.
void mark(int limit)Размещение метки в текущей позиции входного потока
boolean markSupported()Функция проверки поддержки потоком методов mark() и reset()
boolean ready()Функция проверки готовности объекта для чтения данных, т.е. в нем существует хотя бы один доступный символ. Следует заметить, что результат, равный false, отнюдь не свидетельствует о том, что очередной вызов read приведет к возникновению блокировки, поскольку в промежутке между обращениями к ready и read в поток может поступить очередная порция данных.
void reset()Сброс указателя ввода в ранее установленную позицию метки.
long skip(long count)Функция пропуска указанного в параметре count количества символов ввода. Возвращает количество действительно пропущенных символов. Значение count не должно быть отрицательным.
int read() throws lOExceptionЧтение одного символа данных в виде целого числа в диапазоне от 0 до 65535. Если символов, готовых для чтения, нет ввиду достижения конца потока, то возвращается значение -1. Метод выполняет блокировку до тех пор, пока имеются доступные для чтения символы, не достигнут конец потока либо не выброшено исключение.
abstract int read(char[] buf, int offset, int count) throws lOExceptionЧтение символов и сохранение их в массиве buf типа char. Максимальное количество читаемых символов определяется значением count. Символы записываются в массив, начиная с смещение offset. Содержимое всех остальных элементов массива buf остается неизменным. Метод возвращает количество фактически считанных символов.
Если достигнут конец потока и не считан ни один символ, возвращается -1. Если значение count равно нулю, чтение не производится и возвращается 0.
Метод выполняет блокировку до тех пор, пока имеются доступные для чтения символы не достигнут конец потока либо не выброшено исключение.
int read(char[] buf) throws IOExceptionМетод аналогичен предыдущему при условии, offset = 0, count = buf.length.

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

Наследники класса Reader

  • BufferedReader — буферизированный входной символьный поток; увеличивает производительность за счёт буферизации ввода;
  • CharArrayReader — входной поток чтения символьного массива;
  • FileReader — входной поток чтения содержимого файла; в конструкторе класса нужно указать либо путь к файлу, либо объект типа File;
  • FilterReader — фильтрующий читатель;
  • InputStreamReader — входной поток, транслирующий байты в символы;
  • LineNumberReader — входной поток, подсчитывающий строки;
  • PipedReader — входной канал;
  • PushbackReader — входной поток, позволяющий возвращать символы обратно в поток;
  • StringReader — входной поток, читающий из строки.

Класс BufferedReader

Широкораспространенный в использовании класс BufferedReader считывает текст из символьного потока ввода, буферизируя прочитанные символы. Использование буфера призвано увеличить производительность чтения данных из потока.

BufferedReader имеет следующие конструкторы :

Примеры BufferedReader

В качестве примера рассмотрим программу подсчета общего количества символов и числа пробелов в символьном потоке чтения:

Программе в качестве параметра передается имя файла в командной строке. Переменная in представляет символьный поток чтения. Если имя файла не задано, то используется стандартный поток ввода, System.in, после «вложения» его в объект типа InputStreamReader, который выполняет преобразование байтового потока ввода в символьный поток чтения. В противном случае создается объект типа FileReader, расширяющего класс Reader.

В цикле for подсчитывается общее количество символов в файле. Кроме этого, с использованием метода isWhitespace класса Character выявляются символы пробела и вычисляется их количество, а затем на экран выводится результат.

Абстрактный класс Writer

Абстрактный класс Writer обеспечивает поддержку символьного потока записи аналогично тому, как это делает OutputStream, реализующий модель байтового потока вывода. Многие методы Writer схожи с теми, которые объявлены в OutputStream; помимо этого, в классе Writer предусмотрены некоторые другие полезные версии метода write.

Методы класса Writer

Все методы класса вызывают исключение IOException при возникновении ошибки.

МетодОписание
append(char c)Добавление символа в конец вызывающего выходного потока.
abstract void close() throws lOExceptionЗакрытие ранее открытого поток записи; при необходимости выполняется сброс потока. Метод используется для высвобождения ресурсов, связанных с потоком (таких как дескрипторы открытых файлов). Любые попытки обращения к закрытому потоку приводят к выбрасыванию исключения типа lOException, но повторное закрытие потока эффектов не вызывает.
abstract void flush()Сброс потока. Если поток сохраняет в промежуточном буфере некоторое число символов, переданных методами write различных версий, flush провоцирует выполнение операции непосредственной записи данных в объект-получатель. Затем, если получателем является другой поток, тот в свою очередь также сбрасывается. Таким образом, единственный вызов flush приводит к сбросу всех буферов в цепочке взаимосвязанных потоков. Если поток не относится к категории буферизованных, никакие действия не выполняются.
void write(int char) throws lOExceptionЗапись символа в выходной поток. Метод выполняет блокировку потока до тех пор, пока символ не будет записан.
abstract void write(char[] buf, int offset, int count) throws lOExceptionЗапись count символов массива buf, начиная с элемента buf [offset]. Метод выполняет блокировку до тех пор, пока символы не будут записаны.
void write(char[] buf) throws lOExceptionМетод аналогичен предыдущему при условии offset = 0 и count = buf.length.
void write(String string, int offset, int count) throws lOExceptionЗапись count символов строки string, начиная с символа string.charAt(offset).
void write(String string) throws lOExceptionМетод аналогичен предыдущему при условии offset = 0 и count = string.length()).
Читать еще:  Unit test javascript

Классы, производные от Writer, должны реализовать вариант метода write, связанного с записью символов из части массива, а также методов close и flush. Все остальные методы Writer основаны на трех методах, названных выше. Это отличает Writer от класса OutputStream, в котором в качестве базового метода вывода предусмотрен вариант write, осуществляющий вывод одного байта, а для методов flush и close предложены реализации по умолчанию.

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

Наследники класса Writer

  • BufferedWriter — буферизированный выходной символьный поток; позволяет повысить производительность за счёт снижения количества операций физической записи в выходное устройство;
  • CharArrayWriter — выходной поток, который пишет в символьный массив;
  • FileWriter — выходной поток, пишущий в файл; в конструкторе можно определить вывод в конец файла. Создание объекта не зависит от наличия файла, он будет создан в случае необходимости. Если файл существует и он доступен только для чтения, то передаётся исключение IOException
  • FilterWriter — фильтрующий писатель
  • OutputStreamWriter -выходной поток, транслирующий байты в символы
  • PipedWriter — выходной канал
  • PrintWriter — выходной поток, включающий методы print() и println()
  • StringWriter — выходной поток, пишущий в строку

Класс BufferedWriter

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

BufferedWriter имеет следующие конструкторы :

В качестве параметра out конструктор BufferedWriter принимает поток вывода, в который надо осуществить запись. Второй параметр size указывает на размер буфера.

Пример использования классов FileWriter и BufferedWriter :

Java.io.Reader класс в Java

Это абстрактный класс для чтения символьных потоков. Единственные методы, которые должен реализовывать подкласс, это read (char [], int, int) и close (). Однако большинство подклассов переопределяют некоторые из методов, определенных здесь, чтобы обеспечить более высокую эффективность, дополнительную функциональность или оба.
Конструкторы:

  • protected Reader (): Создает новый читатель потока символов, критические секции которого синхронизируются на самом читателе.
  • protected Reader (Object lock): Создает новое устройство чтения символьного потока, критические секции которого будут синхронизироваться с данным объектом.

Методы:

  • abstract void close (): закрывает поток и освобождает любые системные ресурсы, связанные с ним. Как только поток будет закрыт, дальнейшие вызовы read (), ready (), mark (), reset () или skip () вызовут IOException. Закрытие ранее закрытого потока не имеет никакого эффекта.
  • void mark (int readAheadLimit): отмечает текущую позицию в потоке. Последующие вызовы reset () будут пытаться переместить поток в эту точку. Не все потоки ввода символов поддерживают операцию mark ().
  • boolean markSupported (): сообщает, поддерживает ли этот поток операцию mark (). Реализация по умолчанию всегда возвращает false. Подклассы должны переопределить этот метод.
  • int read (): читает один символ. Этот метод будет блокироваться до тех пор, пока символ не станет доступным, не произойдет ошибка ввода-вывода или не будет достигнут конец потока.
    Подклассы, которые намереваются поддерживать эффективный односимвольный ввод, должны переопределить этот метод.
  • int read (char [] cbuf): читает символы в массив. Этот метод будет блокировать, пока не будет доступен какой-либо ввод, не произойдет ошибка ввода-вывода или не будет достигнут конец потока.
  • abstract int read (char [] cbuf, int off, int len): считывает символы в часть массива. Этот метод блокирует, пока не будет доступен какой-либо ввод, не произойдет ошибка ввода-вывода или не будет достигнут конец потока ,
  • int read (CharBuffer target): Пытается прочитать символы в указанном буфере символов. Буфер используется как хранилище символов как есть: единственные сделанные изменения — это результаты операции put. Переворот или перемотка буфера не выполняются.
  • boolean ready (): сообщает, готов ли этот поток для чтения.
  • void reset (): Сбрасывает поток. Если поток был помечен, попытайтесь изменить его положение на отметке. Если поток не был отмечен, попытайтесь сбросить его каким-либо образом, соответствующим конкретному потоку, например, переместив его в начальную точку. Не все потоки ввода символов поддерживают операцию сброса (), а некоторые поддерживают сброс () без поддержки метки ().
  • long skip (long n): пропускает символы. Этот метод блокируется, пока не будут доступны некоторые символы, не произойдет ошибка ввода-вывода или не будет достигнут конец потока.

// Java-программа, демонстрирующая методы Reader

public static void main(String[] args) throws IOException

Классы символьных потоков

1. Класс Reader

Класс Reader — абстрактный класс, определяющий символьный потоковый ввод. В случае ошибок все методы класса передают исключение IOException.

Методы класса Reader:

Существует 3 основных read()-метода:

  • int read()— возвращает представление очередного доступного символа во входном потоке в виде целого числа.
  • int read(char[] buffer)— пытается прочесть максимум buffer.length символов из входного потока в массив buffer. Возвращает количество символов, в действительности прочитанных из потока.
  • int read(char[] buffer, int offset, int length)— пытается прочесть максимум length символов, расположив их в массиве buffer, начиная с элемента offset. Возвращает количество реально прочитанных символов.
  • close() – метод закрывает поток.

2. Класс Writer

Класс Writer — абстрактный класс, определяющий символьный потоковый вывод. В случае ошибок все методы класса передают исключение IOException.

Методы класса Writer:

Существуют 5 основных write()-метода:

  • void write(int c) – записывает один символ в поток.
  • void write(char[] buffer) – записывает массив символов в поток.
  • void write(char[] buffer, int offset, int length) – записывает в поток подмассив символов длиной length, начиная с позиции offset.
  • void write(String aString)– записывает строку в поток.
  • void write(String aString, int offset, int length) – записывает в поток подстроку символов длиной length, начиная с позиции offset.

3. Класс FileWriter

Класс FileWriter создаёт объект класса, производного от класса Writer, который вы можете применять для записи файла. Создание объекта не зависит от наличия файла, он будет создан в случае необходимости. Если файл существует и он доступен только для чтения, то передаётся исключение IOException.

4. Класс FileReader

Класс FileReader, производный от класса Reader, можно использовать для чтения содержимого файла. В конструкторе класса нужно указать либо путь к файлу, либо объект типа File.

Пример 1. Использование FileWriter и FileReader

5. Класс BufferedWriter

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

Читать еще:  Интерфейс cloneable java

По сравнению с классом FileWriter, BufferedWriter записывает относительно большие куски данных в файл, минимизируя количество обращений к файлу. Другими словами операции проходят быстрее.

Добавляет метод void newLine().

Конструкторы класса BufferedWriter:

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

Пример 2. Использование класса BufferedWriter

6. Класс BufferedReader

Класс BufferedReader считывает текст из символьного потока ввода, буферизируя прочитанные символы. Использование буфера призвано увеличить производительность чтения данных из потока.

Добавляет метод String readLine().

Конструкторы класса BufferedReader:

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

Пример 3. Использование класса BufferedReader

7. Класс PrintWriter

Класс PrintWriter расширяет класс Writer. Содержит методы для форматирования.

Конструкторы класса PrintWriter:

  • PrintWriter(File file) — автоматически добавляет информацию в указанный файл.
  • PrintWriter(String fileName) — автоматически добавляет информацию в файл по указанному имени.
  • PrintWriter(OutputStream out) — для вывода информации используется существующий объект OutputStream, автоматически сбрасывая в него данные.
  • PrintWriter(Writer out) — для вывода информации используется существующий объект Writer, в который автоматически идет запись данных.

Методы класса PrintWriter:

  • println() — вывод строковой информации с переводом строки.
  • print() — вывод строковой информации без перевода строки.
  • printf()— форматированный вывод.
  • format() — форматированный вывод.

Пример 4. Использование класса PrintWriter

8. Классы символьных потоков

Класс

Назначение

BufferedReader

Буферизованный входной символьный поток.

BufferedWriter

Буферизованный выходной символьный поток.

CharArrayReader

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

CharArrayWriter

Выходной поток, который пишет в символьный массив.

FileReader

Входной поток, читающий файл.

FileWriter

Выходной поток, пишущий в файл.

FilterReader

FilterWriter

InputStreamReader

Входной поток, транслирующий байты в символы.

LineNumberReader

Входной поток, подсчитывающий строки.

OutputStreamWriter

Выходной поток, транслирующий байты в символы.

PipedReader

PipedWriter

PrintWriter

Выходной поток, включающий print() и println().

PushbackReader

Входной поток, позволяющий возвращать символы обратно в поток.

Reader

Абстрактный класс, описывающий символьный ввод.

StringReader

Входной поток, читающий из строки.

StringWriter

Выходной поток, пишущий в строку.

Writer

Абстрактный класс, описывающий символьный вывод.

Пакет java.io

Классы 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.1. Соответствие классов для байтовых и символьных потоков.

Байтовый потокСимвольный поток
InputStreamReader
OutputStreamWriter
ByteArrayInputStreamCharArrayReader
ByteArrayOutputStreamCharArrayWriter
Нет аналогаInputStreamReader
Нет аналогаOutputStreamWriter
FileInputStreamFileReader
FileOutputStreamFileWriter
FilterInputStreamFilterReader
FilterOutputStreamFilterWriter
BufferedInputStreamBufferedReader
BufferedOutputStreamBufferedWriter
PrintStreamPrintWriter
DataInputStreamНет аналога
DataOutputStreamНет аналога
ObjectInputStreamНет аналога
ObjectOutputStreamНет аналога
PipedInputStreamPipedReader
PipedOutputStreamPipedWriter
StringBufferInputStreamStringReader
Нет аналогаStringWriter
LineNumberInputStreamLineNumberReader
PushBackInputStreamPushBackReader
SequenceInputStreamНет аналога

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

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

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

Классы-мосты InputStreamReader и OutputStreamWriter при преобразовании символов также используют некоторую кодировку. Ее можно задать, передав в конструктор в качестве аргумента ее название. Если оно не будет соответствовать никакой из известных кодировок, будет брошено исключение UnsupportedEncodingException . Вот некоторые из корректных значений этого аргумента (чувствительного к регистру!) для распространенных кодировок: «Cp1251» , «UTF-8» , «8859_1» и т.д.

Класс StreamTokenizer

Экземпляр StreamTokenizer создается поверх существующего объекта, либо InputStream , либо Reader . Как и java.util.StringTokenizer , этот класс позволяет разбивать данные на лексемы ( token ), выделяемые из потока по определенным свойствам. Поскольку работа ведется со словами, конструктор , принимающий InputStream , объявлен как deprecated (предлагается оборачивать байтовый поток классом InputStreamReader и вызывать второй конструктор ). Общий принцип работы такой же, как и у StringTokenizer , – задаются параметры разбиения, после чего вызывается метод nextToken() , пока не будет достигнут конец потока . Способы задания разбиения у StreamTokenizer довольно разнообразны, но просты, и поэтому здесь не рассматриваются.

Читать еще:  Выборочному наблюдению присущи ошибки

Работа с файловой системой

Класс File

Если классы потоков осуществляют реальную запись и чтение данных, то класс File – это вспомогательный инструмент, призванный обеспечить работу с файлами и каталогами.

Объект класса File является абстрактным представлением файла и пути к нему. Он устанавливает только соответствие с ним, при этом для создания объекта неважно, существует ли такой файл на диске. После создания можно выполнить проверку, вызвав метод exists , который возвращает значение true , если файл существует. Создание или удаление объекта класса File никоим образом не отображается на реальных файлах. Для работы с содержимым файла можно получить экземпляры FileI/OStream .

Объект File может указывать на каталог (узнать это можно путем вызова метода isDirectory ). Метод list возвращает список имен (массив String ) содержащихся в нем файлов (если объект File не указывает на каталог – будет возвращен null ).

Следующий пример демонстрирует использование объектов класса File :

При выполнении этой программы на экран будут выведены названия (в каноническом виде) всех файлов, с расширением .java , содержащихся в текущем каталоге и всех его подкаталогах.

Для определения того, что файл имеет расширение .java , использовался интерфейс FileFilter с реализацией в виде внутреннего класса NameFilter . Интерфейс FileFilter определяет только один метод accept , возвращающий значение, определяющее, попадает ли переданный файл в условия фильтрации. Помимо этого интерфейса, существует еще одна разновидность интерфейса фильтра – FilenameFilter , где метод accept определен несколько иначе: он принимает не объект файла к проверке, а объект File , указывающий на каталог, где находится файл для проверки, и строку его названия. Для проверки совпадения, с учетом регулярных выражений, нужно соответствующим образом реализовать метод accept . В конкретном приведенном примере можно было обойтись и без использования интерфейсов FileFilter или FilenameFilter . На практике их можно использовать для вызова методов list объектов File – в этих случаях будут возвращены файлы с учетом фильтра.

Также класс File предоставляет возможность получения некоторой информации о файле.

  • Методы canRead и canWrite – возвращается boolean значение, можно ли будет приложению производить чтение и изменение содержимого из файла, соответственно.
  • getName – возвращает строку – имя файла (или каталога).
  • getParent , getParentName – возвращают каталог, где файл находится в виде объекта и строки названия File , соответственно.
  • getPath – возвращает путь к файлу (при этом в строку преобразуется абстрактный путь, на который указывает объект File ).
  • isAbsolutely – возвращает boolean значение, является ли абсолютным путь, которым указан файл. Определение, является ли путь абсолютным, зависит от системы, где запущена Java-машина. Так, для Windows абсолютный путь начинается с указания диска, либо символом » . Для Unix абсолютный путь начинается символом ‘/’.
  • isDirectory , isFile – возвращает boolean значение, указывает ли объект на каталог либо файл, соответственно.
  • isHidden – возвращает boolean значение, указывает ли объект на скрытый файл.
  • lastModified – дата последнего изменения.
  • length – длина файла в байтах.

Также можно изменить некоторые свойства файла – методы setReadOnly , setLastModified , назначение которых очевидно из названия. Если нужно создать файл на диске, это позволяют сделать методы createNewFile , mkDir , mkDirs . Соответственно, createNewFile создает пустой файл (если таковой еще не существует), mkDir создает каталог, если для него все родительские уже существуют, а mkDirs создаст каталог вместе со всеми необходимыми родительскими.

Файл можно и удалить – для этого предназначены методы delete и deleteOnExit . При вызове метода delete файл будет удален сразу же, а при вызове deleteOnExit по окончании работы Java-машины (только при корректном завершении работы) отменить запрос уже невозможно.

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

Класс RandomAccessFile

Этот класс реализует сразу два интерфейса – DataInput и DataOutput – следовательно, может производить запись и чтение всех примитивных типов Java. Эти операции, как следует из названия, производятся с файлом. При этом их можно производить поочередно, произвольным образом перемещаясь по файлу с помощью вызова метода seek(long) (переводит на указанную позицию в файле). Узнать текущее положение указателя в файле можно вызовом метода getFilePointer .

При создании объекта этого класса конструктору в качестве параметров нужно передать два параметра: файл и режим работы. Файл, с которым будет проводиться работа, указывается либо с помощью String – название файла, либо объектом File , ему соответствующим. Режим работы ( mode ) – представляет собой строку либо «r» (только чтение), либо «rw» (чтение и запись). Попытка открыть несуществующий файл только на чтение приведет к исключению FileNotFoundException . При открытии на чтение и запись он будет незамедлительно создан (или же будет брошено исключение FileNotFoundException , если это невозможно осуществить).

После создания объекта RandomAccessFile можно воспользоваться методами интерфейсов DataInput и DataOutput для проведения с файлом операций считывания и записи. По окончании работы с файлом его следует закрыть, вызвав метод close .

Заключение

В данной лекции вы познакомились с таким важным понятием, как потоки данных ( stream ). Потоки являются очень эффективным способом решения задач, связанных с передачей и получением данных, независимо от особенностей используемых устройств ввода/вывода. Как вы теперь знаете, именно в пакете java.io содержатся стандартные классы, решающие задачи обмена данными в самых различных форматах.

Были описаны базовые классы байтовых потоков InputStream и OutputStream , а также символьных потоков Reader и Writer . Все классы потоков явным или неявным образом наследуются от них. Краткий обзор показал, для чего предназначен каждый класс , как с ним работать, какие классы не рекомендованы к использованию. Изучено, как передавать в потоки значения примитивных типов Java . Особое внимание было уделено операциям с объектами, для которых существует специальный механизм сериализации .

Наконец, были описаны классы для работы с файловой системой – File и RandomAccessFile .

Ссылка на основную публикацию
Adblock
detector