Ответы на вопросы по ревью 4. Java io. Ключевым понятием здесь является понятие потока
Скачать 1.93 Mb.
|
Почему метод read класса InputStream возвращает int, а не byteПопробуйте выполнить такой код: byte myByte = -3; // 11111101 byte[] myArray = {myByte}; InputStream in = new ByteArrayInputStream(myArray); int myInt = in.read(); System.out.println(myInt); // 253 В консоль выводится 253, а не -3. Почему так происходит? Тип данных int в Java является дополненнным до двух целым числом и использует 32 бита вместо 8. В 32х битном виде число 253 будет: 00000000000000000000000011111101 т. е. метод read() возвращает не само значение byte, а его представление в 32х битном виде. Как хранятся значения в int в byte| число | 32 bit | 8 bit | ----- -------------------------------- -------- | . . | . . . . . . . . . . . . . . . . | | . . | . . . . . . . . . . . . . . . . | | -128 | 11111111111111111111111110000000 | 10000000 | | -127 | 11111111111111111111111110000001 | 10000001 | | -126 | 11111111111111111111111110000010 | 10000010 | | -125 | 11111111111111111111111110000011 | 10000011 | | . . | . . . . . . . . . . . . . . . . | . . . . | | . . | . . . . . . . . . . . . . . . . | . . . . | | -2 | 11111111111111111111111111111110 | 11111110 | | -1 | 11111111111111111111111111111111 | 11111111 | | 0 | 00000000000000000000000000000000 | 00000000 | | 1 | 00000000000000000000000000000001 | 00000001 | | 2 | 00000000000000000000000000000010 | 00000010 | | . . | . . . . . . . . . . . . . . . . | . . . . | | . . | . . . . . . . . . . . . . . . . | . . . . | | 125 | 00000000000000000000000001111101 | 01111101 | | 126 | 00000000000000000000000001111110 | 01111110 | | 127 | 00000000000000000000000001111111 | 01111111 | | . . | . . . . . . . . . . . . . . . . | | . . | . . . . . . . . . . . . . . . . | Диапазон byte в Java лежит от -128 до 127, а возвращаемое значение метода read() лежит в диапазоне от 0 до 255. Что происходит с числом byte в методе readЧтобы получить представление byte в int в методе read() используется побитовое «И» c числом 255, т. е. убираем лидирующие единицы. | число | 32 bit | ----- -------------------------------- | -3 | 11111111111111111111111111111101 | И | 255 | 00000000000000000000000011111111 | = | 253 | 00000000000000000000000011111101 | Чтобы из представления получить обратно значение byte в int, нужно выполнить обратную операцию побитовое «ИЛИ» c числом -256, т. е. добавляем лидирующие единицы. | число | 32 bit | ----- -------------------------------- | 253 | 00000000000000000000000011111101 | ИЛИ | -256 | 11111111111111111111111100000000 | = | -3 | 11111111111111111111111111111101 | Что происходит с числом byte == -1 в методе read()То же самое: убираем лидирующие единицы. | число | 32 bit | ----- -------------------------------- | -1 | 11111111111111111111111111111111 | И | 255 | 00000000000000000000000011111111 | = | 255 | 00000000000000000000000011111111 | 5) Как создать файл на компьютере с помощью java. Класс File, определенный в пакете java.io, не работает напрямую с потоками. Его задачей является управление информацией о файлах и каталогах. Хотя на уровне операционной системы файлы и каталоги отличаются, но в Java они описываются одним классом File. В зависимости от того, что должен представлять объект File - файл или каталог, мы можем использовать один из конструкторов для создания объекта:
Например:
Класс File имеет ряд методов, которые позволяют управлять файлами и каталогами. Рассмотрим некоторые из них: boolean createNewFile(): создает новый файл по пути, который передан в конструктор. В случае удачного создания возвращает true, иначе false boolean delete(): удаляет каталог или файл по пути, который передан в конструктор. При удачном удалении возвращает true. boolean exists(): проверяет, существует ли по указанному в конструкторе пути файл или каталог. И если файл или каталог существует, то возвращает true, иначе возвращает false String getAbsolutePath(): возвращает абсолютный путь для пути, переданного в конструктор объекта String getName(): возвращает краткое имя файла или каталога String getParent(): возвращает имя родительского каталога boolean isDirectory(): возвращает значение true, если по указанному пути располагается каталог boolean isFile(): возвращает значение true, если по указанному пути находится файл boolean isHidden(): возвращает значение true, если каталог или файл являются скрытыми long length(): возвращает размер файла в байтах long lastModified(): возвращает время последнего изменения файла или каталога. Значение представляет количество миллисекунд, прошедших с начала эпохи Unix String[] list(): возвращает массив файлов и подкаталогов, которые находятся в определенном каталоге File[] listFiles(): возвращает массив файлов и подкаталогов, которые находятся в определенном каталоге boolean mkdir(): создает новый каталог и при удачном создании возвращает значение true boolean renameTo(File dest): переименовывает файл или каталог Работа с каталогамиЕсли объект File представляет каталог, то его метод isDirectory() возвращает true. И поэтому мы можем получить его содержимое - вложенные подкаталоги и файлы с помощью методов list() и listFiles(). Получим все подкаталоги и файлы в определенном каталоге:
Теперь выполним еще ряд операций с каталогами, как удаление, переименование и создание:
Работа с файламиРабота с файлами аналогична работе с каталога. Например, получим данные по одному из файлов и создадим еще один файл:
При создании нового файла метод createNewFile() в случае неудачи выбрасывает исключение IOException, поэтому нам надо его отлавливать, например, в блоке try...catch, как делается в примере выше. 6) Как удалить директорию с файлами. Java не может удалять папки с данными в нем. Перед удалением папки необходимо удалить все файлы. использовать что-то вроде: String []entries = index.list (); for (String s: entries) { File currentFile = new File (index.getPath (), s); currentFile.delete ();} тогда вы сможете удалить папку, используя index.delete ().
deleteDirectorypublic static void deleteDirectory(File directory) throws IOException Deletes a directory recursively. Parameters: directory - directory to delete Throws: IOException - in case deletion is unsuccessful IllegalArgumentException - if directory does not exist or is not a directory deleteQuietlypublic static boolean deleteQuietly(File file) Deletes a file, never throwing an exception. If file is a directory, delete it and all sub-directories. The difference between File.delete() and this method are: A directory to be deleted does not have to be empty. No exceptions are thrown when a file or directory cannot be deleted. Parameters: file - file or directory to delete, can be null Returns: true if the file or directory was deleted, otherwise false Since: 1.4 forceDeletepublic static void forceDelete(File file) throws IOException Deletes a file. If file is a directory, delete it and all sub-directories. The difference between File.delete() and this method are: A directory to be deleted does not have to be empty. You get exceptions when a file or directory cannot be deleted. (java.io.File methods returns a boolean) Parameters: file - file or directory to delete, must not be null Throws: NullPointerException - if the directory is null FileNotFoundException - if the file was not found IOException - in case deletion is unsuccessful forceDeleteOnExitpublic static void forceDeleteOnExit(File file) throws IOException Schedules a file to be deleted when JVM exits. If file is directory delete it and all sub-directories. Parameters: file - file or directory to delete, must not be null Throws: NullPointerException - if the file is null IOException - in case deletion is unsuccessful Это лучшее решение для Java 7+: public static void deleteDirectory(String directoryFilePath) throws IOException { Path directory = Paths.get(directoryFilePath); if (Files.exists(directory)) { Files.walkFileTree(directory, new SimpleFileVisitor () { @Override public FileVisitResult visitFile(Path path, BasicFileAttributes basicFileAttributes) throws IOException { Files.delete(path); return FileVisitResult.CONTINUE; } @Override public FileVisitResult postVisitDirectory(Path directory, IOException ioException) throws IOException { Files.delete(directory); return FileVisitResult.CONTINUE; } }); } } 7) Что такое сериализация и десериализация. Сериализация представляет процесс записи состояния объекта в поток, соответственно процесс извлечения или восстановления состояния объекта из потока называется десериализацией. Сериализация очень удобна, когда идет работа со сложными объектами. Интерфейс SerializableСразу надо сказать, что сериализовать можно только те объекты, которые реализуют интерфейс Serializable. Этот интерфейс не определяет никаких методов, просто он служит указателем системе, что объект, реализующий его, может быть сериализован. Сериализация. Класс ObjectOutputStreamДля сериализации объектов в поток используется класс ObjectOutputStream. Он записывает данные в поток. Для создания объекта ObjectOutputStream в конструктор передается поток, в который производится запись:
Для записи данных ObjectOutputStream использует ряд методов, среди которых можно выделить следующие: void close(): закрывает поток void flush(): очищает буфер и сбрасывает его содержимое в выходной поток void write(byte[] buf): записывает в поток массив байтов void write(int val): записывает в поток один младший байт из val void writeBoolean(boolean val): записывает в поток значение boolean void writeByte(int val): записывает в поток один младший байт из val void writeChar(int val): записывает в поток значение типа char, представленное целочисленным значением void writeDouble(double val): записывает в поток значение типа double void writeFloat(float val): записывает в поток значение типа float void writeInt(int val): записывает целочисленное значение int void writeLong(long val): записывает значение типа long void writeShort(int val): записывает значение типа short void writeUTF(String str): записывает в поток строку в кодировке UTF-8 void writeObject(Object obj): записывает в поток отдельный объект Эти методы охватывают весь спектр данных, которые можно сериализовать. Например, сохраним в файл один объект класса Person:
Десериализация. Класс ObjectInputStreamКласс ObjectInputStream отвечает за обратный процесс - чтение ранее сериализованных данных из потока. В конструкторе он принимает ссылку на поток ввода:
Функционал ObjectInputStream сосредоточен в методах, предназначенных для чтения различных типов данных. Рассмотрим основные методы этого класса: void close(): закрывает поток int skipBytes(int len): пропускает при чтении несколько байт, количество которых равно len int available(): возвращает количество байт, доступных для чтения int read(): считывает из потока один байт и возвращает его целочисленное представление boolean readBoolean(): считывает из потока одно значение boolean byte readByte(): считывает из потока один байт char readChar(): считывает из потока один символ char double readDouble(): считывает значение типа double float readFloat(): считывает из потока значение типа float int readInt(): считывает целочисленное значение int long readLong(): считывает значение типа long short readShort(): считывает значение типа short String readUTF(): считывает строку в кодировке UTF-8 Object readObject(): считывает из потока объект Например, извлечем выше сохраненный объект Person из файла:
Теперь совместим сохранение и восстановление из файла на примере списка объектов:
Исключение данных из сериализацииПо умолчанию сериализуются все переменные объекта. Однако, возможно, мы хотим, чтобы некоторые поля были исключены из сериализации. Для этого они должны быть объявлены с модификатором transient. Например, исключим из сериализации объекта Person переменные height и married:
8) Назовите несколько форматов сериализации. Что такое «сериализация»? Опишите процесс сериализации/десериализации с использованием Serializable. Как изменить стандартное поведение сериализации/десериализации? Как исключить поля из сериализации? Что обозначает ключевое слово transient? Какое влияние оказывают на сериализуемость модификаторы полей static и final Как не допустить сериализацию? Как создать собственный протокол сериализации? Какая роль поля serialVersionUID в сериализации? Когда стоит изменять значение поля serialVersionUID? В чем проблема сериализации Singleton? Какие существуют способы контроля за значениями десериализованного объекта |