Электронная библиотека книг Александра Фролова и Григория Фролова.
Shop2You.ru Создайте свой интернет-магазин
Библиотека
Братьев
Фроловых
[Назад]

Библиотека примеров приложений Java

Оглавление
Выбор файлов
Простейший редактор текста
Копирование файлов UNICODE
Сохранение объекта Java в файле
Произвольные классы и файлы
Буферизация потоков
Разбор конфигура-
ционного файла

Работа с консолью
Работа с классом PrintWriter
Разбор строк класса String
Загрузка и просмотр изображений
Потоки в оперативной памяти
Конвейерные потоки
Комбинирование двух потоков
Комбинирование нескольких потоков
Поиск слова в текстовом файле
Произвольный доступ к файлу
Информация о файле
Работа с каталогами
Просмотр содержимого каталога
Просмотр каталога с фильтром
Панель для выбора каталога
Список системных свойств
Сохранение списка системных свойств
Контрольная сумма файла
Копирование, переименование, удаление файлов
Архивы ZIP
Создание архива ZIP
Распаковка архива ZIP
Обход дерева каталогов

Назад Вперед

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) вы можете рисовать мышью прямые линии.

pic1.gif (3660 bytes)

Рис. 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;    
}

Назад Вперед

[Назад]