Назад
Вперед
7.4. Сохранение объекта Java в файле
Мы покажем как сохранить содержимое объекта
стандартного класса Vector в файле и восстановить
его, пользуясь классами ObjectOutputStream и ObjectInputStream.
Исходный текст примера
Архив проекта для Java WorkShop 2.0
Немного теории
При помощи классов ObjectOutputStream и ObjectInputStream
приложение Java может, соответственно, сохранять
в потоке содержимое примитивных типов данных и
объектов Java, а также восстанавливать это
содержимое.
Для того чтобы вы могли поступать подобным
образом с произвольными объектами Java, они должны
реализовывать интерфейс java.io.Serializable. Кроме того,
в соответствующих классах должен быть
предусмотрен конструктор, не имеющий параметров.
Ниже мы перечислили самые интересные методы
класса ObjectOutputStream.
write(byte[]);
write(byte[], int, int);
write(int);
writeBoolean(boolean);
writeByte(int);
writeBytes(String);
writeChar(int);
writeChars(String);
writeDouble(double);
writeFloat(float);
writeInt(int);
writeLong(long);
writeShort(int);
writeUTF(String);
writeObject(Object);
Обратите внимание на метод writeObject - именно он
обеспечивает сохранение в потоке содержимое
объекта, реализующего интерфейс java.io.Serializable.
В класса ObjectInputStream имеется набор методов, с
помощью которых можно восстановить содержимое
объектов, сохраненных в потоке класса ObjectOutputStream:
read();
read(byte[], int, int);
readBoolean();
readByte();
readChar();
readDouble();
readFloat();
readFully(byte[]);
readFully(byte[], int, int);
readInt();
readLine();
readLong();
readShort();
readUnsignedByte();
readUnsignedShort();
readUTF();
readObject();
Восстановление объекта эквивалентно вызову
соответствующего конструктора, не имеющего
параметров, с последующим восстановлением
содержимого полей класса.
Описание примера
В окне нашего автономного приложения DrawAndSave
(рис. 1) вы можете рисовать мышью прямые линии.
Рис. 1. Главное окно приложения DrawAndSave
Нарисованное изображение легко сохранить в
файле, выбрав из меню File строку Save As, а затем
восстановить при помощи строки Open этого же меню.
Двойной щелчок клавишей мыши в окне приложения
стирает все нарисованные линии.
Рассмотрим исходный текст приложения.
Главный класс приложения DrawAndSave
Главный класс нашего приложения выглядит
достаточно просто:
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import java.io.*;
public class DrawAndSave
{
public static void main(String args[])
{
FrameWindow frame;
frame = new FrameWindow("Draw and save");
frame.setVisible(true);
}
}
Здесь мы создаем главное окно приложения как
объекта класса FrameWindow и отображаем его на экране.
Класс FrameWindow
Класс FrameWindow определяет поведение главного
окна и реализует множество интерфейсов:
class FrameWindow extends Frame
implements ActionListener, WindowListener,
MouseListener, MouseMotionListener
{
. . .
}
Интерфейс ActionListener служит для обработки событий
от меню приложения.
Интерфейс WindowListener нужен для закрытия
приложения при удалении его главного окна.
С помощью интерфейсов MouseListener и MouseMotionListener мы
отслеживаем действия пользователя с мышью в окне
нашего приложения.
Теперь о полях класса FrameWindow.
Следующие поля хранят ссылки на меню и строки
меню:
MenuBar mb;
Menu mFile;
MenuItem miOpen;
MenuItem miSave;
MenuItem miExit;
Поле fdlg класса FileDialog предназначено для
хранения ссылки на стандратные диалоговые
панели сохранения и загрузки файла:
FileDialog fdlg;
Три поля хранят координаты:
Dimension dmDown = new Dimension(0, 0);
Dimension dmUp = new Dimension(0, 0);
Dimension dmPrev = new Dimension(0, 0);
В переменную dmDown класса Dimension записываются
координаты курсора на момент нажатия клавиши
мыши. Если пользователь нажал клавишу мыши для
того чтобы приступить к рисованию линии, это
будет координатами начала линии.
Когда пользователь отпускает клавишу мыши,
координаты записываются в переменную dmUp.
В процессе рисования линии метод mouseDragged
стирает ранее нарисованную линию и рисует новую.
Координаты конца старой линии хранятся в
переменной dmPrev.
Переменная bDrawing типа boolean хранит текущее
состояние аплета. Когда аплет находится в
состоянии рисования линии, в эту переменную
записывается значение true, а когда нет - значение
false:
boolean bDrawing = false;
И, наконец, переменная lines типа Vector является
динамическим массивом, в котором хранятся
координаты нарисованных линий:
Vector lines;
Конструктор класса FrameWindow
Конструктор выполняет следующие действия.
Прежде всего он вызывает конструктор базового
класса Frame, передавая ему в качестве параметра
заголовок окна:
super(szTitle);
Затем он устанавливает размеры главного окна
приложения:
setSize(400, 300);
Далее конструктор создает меню:
mb = new MenuBar();
mFile = new Menu("File");
miOpen = new MenuItem("Open...");
mFile.add(miOpen);
miSave = new MenuItem("Save As...");
mFile.add(miSave);
mFile.add("-");
miExit = new MenuItem("Exit");
mFile.add(miExit);
mb.add(mFile);
Обработчики событий для строк меню
регистрируются при помощи метода addActionListener:
miOpen.addActionListener(this);
miSave.addActionListener(this);
miExit.addActionListener(this);
Готовое меню подключается к окну приложения:
setMenuBar(mb);
Затем мы подключаем обработчик интерфейса
WindowListener:
this.addWindowListener(this);
На следующем этапе конструктор сбрасывает
индикатор включения режима рисования линии и
создает новый объект класса Vetor, хранящий
координаты линий:
bDrawing = false;
lines = new Vector();
Последнее действие, выполняемое конструктором
- регистрация обработчиков событий от мыши:
this.addMouseMotionListener(this);
this.addMouseListener(this);
Метод paint класса FrameWindow
Первым делом метод paint определяет размеры
главного окна аплета и сохраняет их в переменной
класса dimAppWndDimension:
Dimension dimAppWndDimension = getSize();
Далее он устанавливает цвет фона и цвет
изображения:
setBackground(Color.yellow);
g.setColor(Color.black);
После изменения цвета фона метод paint перебирает
в цикле все элементы вектора lines, рисуя линии:
for (int i=0; i < lines.size(); i++)
{
Rectangle p =
(Rectangle)lines.elementAt(i);
g.drawLine(p.width, p.height,
p.x, p.y);
}
Перед завершением работы метод paint сбрасывает
признак рисования, записывая в поле bDrawing
значение false:
bDrawing = false;
Метод actionPerformed класса FrameWindow
Этот метод обрабатывает события, связанные с
выбором строк из главного меню приложения.
Когда пользователь выбирает из этого меню
строку Open, метод actionPerformed открывает диалоговую
панель для выбора входного файла, в котором
пользователь предварительно сохранил
результаты рисования линий:
fdlg = new FileDialog(this, "Open file",
FileDialog.LOAD);
fdlg.show();
Далее метод открывает поток класса ObjectInputStream и
читает из него объект lines класса Vector, содержащий
координаты нарисованных ранее линий:
ObjectInputStream ois;
try
{
ois = new ObjectInputStream(
new FileInputStream(
fdlg.getDirectory() +
fdlg.getFile()));
lines = (Vector)ois.readObject();
ois.close();
}
catch (IOException ex)
{
System.out.println(ex.toString());
}
catch (ClassNotFoundException ex)
{
System.out.println(ex.toString());
}
Для чтения содержимого объекта мы
воспользовались методом readObject.
Вслед за этим содержимое окна
перерисовывается:
repaint();
При выборе из главного меню File строки Save As
создается стандартная диалоговая панель для
выбора сохраняемого файла:
fdlg = new FileDialog(this,
"Save drawing as...",
FileDialog.SAVE);
fdlg.show();
Далее мы открываем соответствующий поток
класса ObjectOutputStream и сохраняем в нем содержимое
вектора lines с координатами нарисованных линий:
ObjectOutputStream oos;
try
{
oos = new ObjectOutputStream(
new FileOutputStream(
fdlg.getDirectory() +
fdlg.getFile()));
oos.writeObject(lines);
oos.flush();
oos.close();
}
catch (IOException ex)
{
System.out.println(ex.toString());
}
Содержимое объекта lines сохраняется методом
writeObject.
Метод mousePressed класса FrameWindow
Прежде всего метод mousePressed получает и сохраняет
текущие координаты курсора мыши:
int x = e.getX();
int y = e.getY();
Затем метод mouseDown определяет, был ли сделан
одинарный щелчок клавишей мыши, или двойной. Если
был сделан двойной щелчок мышью, метод удаляет
все элементы из массива list, а затем
перерисовывает окно аплета, вызывая метод repaint:
if(e.getClickCount() > 1)
{
lines.removeAllElements();
repaint();
return;
}
Если же был сделан одинарный щелчок клавишей
мыши, метод mouseDown сохраняет текущие координаты
курсора в переменных dmDown и dmPrev, а затем
сбрасывает признак рисования:
dmDown = new Dimension(x, y);
dmPrev = new Dimension(x, y);
bDrawing = false;
Метод mouseReleased класса FrameWindow
В задачу метода mouseReleased входит сохранение
текущих координат курсора мыши в поле dmUp, а также
добавление нового элемента в массив lines:
public void mouseReleased(MouseEvent e)
{
int x = e.getX();
int y = e.getY();
if(bDrawing)
{
dmUp = new Dimension(x, y);
lines.addElement(
new Rectangle(dmDown.width,
dmDown.height, x, y));
repaint();
bDrawing = false;
}
}
Метод mouseDragged класса FrameWindow
Прежде всего метод mouseDragged сохраняет текущие
координаты курсора мыши и получает ссылку на
контекст отображения:
int x = e.getX();
int y = e.getY();
Graphics g = getGraphics();
После получения контекста отображения
включается режим рисования (записью в переменную
bDrawing значения true):
bDrawing = true;
Далее метод mouseDragged стирает линию, которая была
нарисована ранее в процессе предыдущего вызова
этого же метода:
g.setColor(Color.yellow);
g.drawLine(dmDown.width, dmDown.height,
dmPrev.width, dmPrev.height);
Затем метод mouseDragged рисует новую линию черного
цвета, соединяя точку, в которой была нажата
клавиша мыши, с точкой текущего расположения
курсора мыши:
g.setColor(Color.black);
g.drawLine(dmDown.width,
dmDown.height, x, y);
После рисования линии координаты ее конца
сохраняются в поле dmPrev для стирания этой линии
при следующем вызове метода mouseDragged:
dmPrev = new Dimension(x, y);
Метод mouseMoved класса FrameWindow
Метод mouseMoved отключает режим рисования. В
результате перемещение курсора мыши над окном
аплета не приводит к рисованию линий:
public void mouseMoved(MouseEvent e)
{
bDrawing = false;
}
Назад Вперед |