Document 7206105

Download Report

Transcript Document 7206105

Объектно-ориентированный анализ
и программирование
Лекция 14
Ввод/вывод (продолжение)
к.т.н. Гринкруг Е.М. (email: [email protected])
20-May-16
Software Engineering
1
Интерфейс Serializable
• Интерфейс java.io.Serializable:
– Не имеет методов (маркер интерфейс);
– Не вызывает конструктор при воссоздании объекта (но могут
вызываться default-конструкторы несериализуемых суперклассов; при
этом состояние объекта при сериализации/десериализации может не
восстановиться (!));
– Выполняет предопределенную сериализацию / десериализацию с
использованием ObjectOutputStrem / ObjectInputStream, которые могут
«тюнироваться» пользователем путем определения приватных методов:
private void writeObject(java.io.ObjectOutputStream out) throws IOException;
private void readObject(java.io.ObjectInputStream in) throws IOException,
ClassNotFoundException;
– В теле этих методов можно использовать, соответственно, операции
• …out.defaultWriteObject();
• …in.defaultReadObject(); // чтобы вызвать стандартные алгоритмы записи / чтения.
20-May-16
Software Engineering
2
Интерфейс Externalizable
•
•
Если класс не полагается на механизм сериализации (Serizlizable), он может
определить свои собственые средства записи и чтения объектов –
реализовать интерфейс java.io.Externalazable;
Это – «нормальный интерфейс» с методами:
public interface Externalazable extends Serializable {
public void writeExternal (ObjectOutput out) throws IOException;
public void readExternal (ObjectInput in) throws IOException, ClassNotFoundException;
} // в учебнике Хорстмана ... – ошибка (параметры не интерфейсы, а потоки...)
•
•
Механизм сериализации / десериализации в этом случае просто пишет в
поток информацию о классе объекта (при сериализации) и создает новый
экземпляр объекта при считывании (жду вопроса...?);
Остальное должны сделать сами указанные выше методы
–
–
В отличие от сериализации – эти методы общедоступны (public);
Они вызываются КАК СЛЕДСТВИЕ вызовов реализаций
• ObjectOutput.writeObject(Object )
• ObjectInput.readObject()
20-May-16
Software Engineering
3
• Замечания:
– Стандартная сериализация работает довольно медленно
Использование Externalizable может повысить скорость записи /
восстановления объектов;
– Общедоступные методы Externalizable-интерфейса позволяют изменить
состояние существующего объектв (вызовом readExternal(…)) (опять
есть ошибка в русском переводе Хорстмана... – там writeExternal(…))
20-May-16
Software Engineering
4
Управление файлами (класс File)
• Потоковые классы сделаны для работы с содержимым файлов;
• Класс File – для работы с самими файлами.
• Java всегда придерживается принципа «наименьшего общего
знаменателя» при реализации возможностей, связанных с
разными операционными системами; конкретные их особенности
«доиспользуются» вызовами native-методов;
• Простейший конструктор File(String s) получает имя файла
– Если оно – не полное, то поиск идет от текущего каталога;
– Текущий каталог при этом – тот, из которого запущена Java VM (если
JVM запускалась из командной строки).
• Если файла с таким именем не существует, он НЕ создается;
– Фактическое создание файла из объекта класса File делается каким-то
потоком или специальным методом класса File createNewFile(),
который создает новый файл, если его не было (говоря об успехе...).
20-May-16
Software Engineering
5
• Имея объект File, можно узнать, существует ли такой файл
– Методом exists() -> true/false
• Есть конструкторы класса File с указанием каталога (null – означает
текущий каталог) и имени файла в нем. Каталог можно указать:
– Именем (строкой);
– Объектом класса File (объект File объединяет понятия файла и каталога)
• Узнать, что именно означает объект File можно методами:
– isDirectory();
– isFile();
• Сделать объект File, представляющий каталог (директорию) можно
так:
– File tempDir = new File( File.separator + “temp”);
– После чего tempDir.mkdir() – создаст директорию (если ее еще нет...)
20-May-16
Software Engineering
6
• Не следует пользоваться конкретным разделителем имен,
принятым в данной файловой системе; надо пользоваться
константами из класса File: File.separator
– В Win32FileSystem – это backslash (\)
– В Unix – это forward slash (/).
– Надо иметь в виду, что в Java ‘\’ - это “escape - символ” (что это?)
20-May-16
Software Engineering
7
«Новый ввод-вывод» (пакет java.nio)
• Пакет java.nio появился в JDK 1.4 (но до сих пор называется «new
i/o»)
• Отображение файлов в памяти (memory-mapped files) отражает
возможности большинства операционных систем и иногда (для
больших объемов информации) ускоряет работу по сравнению с
традиционными файловыми операциями;
• Покет java.nio имеет для этого средства:
– Получения канала для потока
• Классы FileInputStream, FileOutputStream и RundomAccessFile имеют
метод getChannel(), который возвращает FileChannel;
– Получения ByteBuffer’а от канала
• Класс FileChannel имеет метод map(), который дает MappedByteBuffer;
• MappedByteBuffer extends ByteBuffer.
• При получении буфера у канала указывается режим отображения
(MapMode) и область файла, отображаемую в память (начало и
размер);
20-May-16
Software Engineering
8
•
Java поддерживает три режима отображения:
– FileChannel.MapMode.READ_ONLY
• Создается буфер только для чтения (иначе - exception)
– FileChannel.MapMode.READ_WRITE
• Бефер допускает запись, когда-нибудь результат окажется в файле...
– FileChannel.MapMode.PRIVATE
• В буфер можно писать, но изменения в файл не вносятся.
•
•
Имея ByteBuffer, можно пользоваться его методами для чтения и/или
записи данных;
Буферы поддерживают последовательный и/или произвольный доступ
к данным.
– В буфере определена позиция, которая изменяется в результате
выполнения методов get() и put()
– Возможен произвольный доступ:
например, byte d = buffer.get(i);
– Возможно чтение / pfgbcm массива байтов, например:
get(byte[] bytes); или get(byte[] bytes, int offset, int length);
20-May-16
Software Engineering
9
• Можно читать / писать двоичные представления базовых типов
– getInt(), getLong(), getShort(), getChar(), getFloat(), getDouble();
– putInt(), putLong(), putShort(), putChar(), putFloat(), putDouble();
• При этом предусмотрены указания о способе хранения данных в
файле (ByteOrder.LITTLE_ENDIAN или ByteOrder. BIG_ENDIAN):
– Узнать, каков порядок у буфера:
• ByteOrder bo = buffer.order();
– Установить нужный порядок:
• Buffer.order(ByteOrder.LITTLE_ENDIAN); // или BIG_ENDIAN…
20-May-16
Software Engineering
10
Структура буфера
•
•
•
При отображении файла в памяти создается буфер, имеющий размер на
весь файл или его нужную часть;
Буфер – это массив значений определенного типа; из абстрактного класса
Buffer наследованы ByteBuffer, CharBuffer, FloatBuffer, IntBuffer, и т.п.
Буфер имеет следующие характеристики:
–
–
–
–
Объем (capacity), который не меняется;
Позиция (position) чтения/записи следующего значения;
Граница (limit), за которой чтение/запись не имеют смысла;
Маркер (необязательный) для повторного чтения/записи.
20-May-16
Software Engineering
11
• Буфер в основном применяется для чтения/записи информации
в цикле
– В начале работы текущая позиция равна 0, граница равна объему;
– Метод get() можно вызывать до тех пор, пока
• Remaining = (граница - позиция) > 0
– Метод flip () устанавливает границу равной текущей позиции, а
позицию равной 0;
– Метод clear() ставит позицию в 0 и границу – равной объему;
– Повторные обращения можно организовать с помощью методов
rewind(), mark(), reset().
20-May-16
Software Engineering
12
Блокировка файлов
• Как и работа с отображением файла в память, блокировка файла
является зависимой от операционной системы;
• Блокировка файла бывает нужна, если несколько программ
стремятся работать с одним файлом.
• Файл блокируется вызовами методов класса FileChannel:
– FileLock lock = channel.lock(); // ожидание доступности блокировки...
– FileLock lock = channel.tryLock(); // блокировка или null, если сразу – нет...
• Можно заблокировать часть файла:
FileLock lock(long start, long size, boolean exclusive);
FileLock tryLock(long start, long size, boolean exclusive);
excusive – true, если «исключительная блокировка» (для записи)
exclusive – false, если «совместная блокировка» (для параллельного
чтения); эти средства поддерживаются не всеми операционными
системами...
20-May-16
Software Engineering
13
20-May-16
Software Engineering
14
Платформо-ориентированный код (native code)
• Иногда приходится использовать платформо-ориентированный
код:
– Уже есть готовый программный модуль, который хочется
использовать (OpenGL, например);
– Требуются функции конкретной OS или «железа»;
– «Сугубая» оптимизация для реального времени (на самом деле justin-time компиляция скрадывает разницу с откомпилированным Скодом).
– При использовании native-кода надо обращать внимание на защиту;
• Как правило, пользователи не люббят иметь дело с native-кодом,
и его надо применять только в крайних случаях. Даже
использоване готовых модулей следует считать временной
мерой, стараясь пееписать их в java...
20-May-16
Software Engineering
15
Вызов C-функции из java-программы
• В некотором классе java объявляется native-функция, например,
public native String translateEnglishIntoRussian (String s);
Класс, содержащий эту декларацию native-метода, скомпилируется, но
при выполнении – UnsatisfiedLinkError… - JVM не может найти
нужную функцию. Native-метод может быть или не быть
статическим.
• Теперь надо:
– Создать на языке C «заглушку» (переходник), которая преобразует
вызов их java в обращение к нужной C-фукции; в частности, надо
взять параметры из стека JVM и передать их откомпилированной
C-функции;
– Создать специальную разделяемую библиотеку (dll – в Windows),
которая экспортирует эту «заглушку»;
– Использовать специальный метод java: System.loadLibrary(…),
указав имя этой dll…
20-May-16
Software Engineering
16
• Реализация этой «технологии» такова:
– Сперва компилируется java-класс с native-методами;
– Потом вызывается специальная утилита из каталога jdk/bin под
названием javah.exe параметром которой дается класс-файл. Эта
утилита производит Header-файл (<имя_класса>.h) как исходный
файл для использования С-компилятором. В нем самом
используются jni.h, где определены все необходимые имена...
– В сгенерированном заголовочном файле будет прототип
вызываемой функции, которую надо реализовать на С.
– Все такие реализованные С-функции собираются в dll, например,
myNatives.dll
– В java-классе, где нужны native-методы, делаем статический
инициализатор (когда он будет работать?):
static { System.loadLibrary(“myNatives”); }
– Саму myNatives.dll надо «положить в нужное место» ...
20-May-16
Software Engineering
17
• Имеются детали, связанные с
– Различием вызовов констркторов, статических и нестатических
методов;
– Передачей параметров и возвращаемых значений;
– Работой в мультитредном окружении;
– Передачей ошибок и исключительных ситуаций;
– И т.п.
• Для тех, кто владеет C (C++) эти детали – не проблема.
20-May-16
Software Engineering
18
Q&A
• Have a nice test !
20-May-16
Software Engineering
19