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

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

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

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

Назад Вперед

7.12. Создание потоков в оперативной памяти

На примере аплета в примере демонстрируются методы организации объектно-ориентированного вывода в потоки, созданные в оперативной памяти как объекты классов ByteArrayOutputStream и ввода из потоков, созданных на базе класса ByteArrayInputStream. Вывод и ввод объектов класса Vector выполняется с применением классов ObjectOutputStream и ObjectInputStream, соответственно.

Исходный текст примера

Архив проекта для Java WorkShop 2.0

Демонстрация
(ваш браузер должен уметь работать с аплетами Java JDK 1.1)

Немного теории

При создании приложений и аплетов Java вы также можете работать с объектами оперативной памяти, как с потоками. Это имеет особенное значение для аплетов, которым запрещено обращаться к файлам, расположенным на локальном диске компьютера.

В библиотеке классов Java есть три класса, специально предназначенных для создания потоков в оперативной памяти. Это классы ByteArrayOutputStream, ByteArrayInputStream и StringBufferInputStream.

Класс ByteArrayOutputStream

Класс ByteArrayOutputStream создан на базе класса OutputStream. В нем имеется два конструктора, прототипы которых представлены ниже:

public ByteArrayOutputStream();
public ByteArrayOutputStream(int size);

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

В классе ByteArrayOutputStream определено несколько методов:

public void reset();
public int size();
public byte[] toByteArray();
public void writeTo(OutputStream out);

Метод reset сбрасывает счетчик байт, записанных в выходной поток. С помощью метода size можно определить количество байт данных, записанных в поток.

Метод toByteArray позволяет скопировать данные, записанные в поток, в массив байт. Этот метод возвращает ссылку на созданный для этой цели массива.

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

Для выполнения форматированного вывода в поток, вы должны создать поток на базе таких классов как DataOutputStream или ObjectOutputStream, передав соответствующему конструктору ссылку на поток класса ByteArrayOutputStream.

Класс ByteArrayInputStream

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

public ByteArrayInputStream(byte buf[]);
public ByteArrayInputStream(
  byte buf[], int offset, int length);

Первый конструктор получает через единственный параметр ссылку на массив, который будет использован для создания входного потока. Второй позволяет дополнительно указать смещение offset и размер области памяти length, которая будет использована для создания потока.

Вот несколько методов, определенных в классе ByteArrayInputStream:

public int available();
public int read();
public int read(byte b[],int off, int len);
public void reset();
public long skip(long n);

С помощью метода available можно определить, сколько байт имеется во входном потоке для чтения.

Обычно класс ByteArrayInputStream используется вместе с классом DataInputStream или ObjectInputStream, что позволяет организовать форматный ввод данных.

Класс StringBufferInputStream

Класс StringBufferInputStream предназначен для создания входного потока на базе текстовой строки класса String. Ссылка на эту строку передается конструктору класса StringBufferInputStream через параметр:

public StringBufferInputStream(String s);

В классе StringBufferInputStream определены те же методы, что и в только что рассмотренном классе ByteArrayInputStream.

Описание примера

Наш аплет создан на базе автономного приложения, рассмотренного в разделе "7.4. Сохранение объекта Java в файле". Это приложение позволяет сохранять нарисованные в его окне прямые линии в файле. Так как аплет не может работать с локальными файлами (в JDK версий 1.0 и 1.1), мы выполняем сохранение в потоке, размещенном в оперативной памяти.

В окне нашего аплета имеется три кнопки и панель для рисования линий (рис. 1).

pic1.gif (5464 bytes)

Рис. 1. Окно аплета с нарисованными в нем линиями

Нарисовав что-нибудь внутри желтой панели, вы можете сохранить рисунок, нажав кнопку Save. Если затем, не покидая страницы HTML с аплетом, стереть рисунок кнопкой Clear или двойным щелчком мыши в окне аплета, его нетрудно будет восстановить, нажав кнопку Restore.

Рассмотрим исходный текст аплета.

Главный класс

Главный класс аплета создан на базе класса Applet и реализует интерфейс ActionListener:

import java.applet.Applet;
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import java.io.*;

public class MemoryStream extends Applet
  implements ActionListener
{
  . . .
}

В главном классе определены поля для хранения ссылок на кнопки и на панель рисования класса DrawPanel, определенного в нашем приложении:

Button btnClear;
Button btnSave;
Button btnRestore;
DrawPanel dp;
Метод init главного класса

При инициализации аплета мы создаем три кнопки и добавляем их в окно аплета:

btnClear = new Button("Clear");
btnSave = new Button("Save");
btnRestore = new Button("Restore");
    
add(btnClear);
add(btnSave);
add(btnRestore);

Затем мы подключаем к этим кнопкам обработчики событий:

btnClear.addActionListener(this);
btnSave.addActionListener(this);
btnRestore.addActionListener(this);

На последнем этапе инициализации создается панель рисования класса DrawPanel, которая затем добавляется в окно аплета:

dp = new DrawPanel();
add(dp);
Метод actionPerformed главного класса

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

Когда пользователь нажимает кнопку Clear, метод actionPerformed удаляет панель рисования, а затем создает и добавляет новую, запуская при этом механизм размещения компонент системы Layout Manager:

if(dp != null)
{
  this.remove(dp);
  dp = new DrawPanel();
  add(dp);
  doLayout();
}

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

else if(e.getSource().equals(btnSave))
{
  dp.save();
}

Аналогично, для восстановления изображения вызывается метод restore:

else if(e.getSource().equals(btnRestore))
{
  dp.restore();
}

Затем окно аплета перерисовывается:

repaint();

Класс DrawPanel

Класс DrawPanel создан на базе класса Panel:

class DrawPanel extends Panel
  implements MouseListener, MouseMotionListener
{
  . . .
}

Он реализует интерфейсы MouseListener и MouseMotionListener, необходимые для обработки событий, вызываемых мышью.

Исходный текст класса с таким именем мы уже описывали в примере "7.4. Сохранение объекта Java в файле". Здесь мы рассмотрим только отличия, связанные с использованием потоков, созданных в оперативной памяти.

В классе DrawPanel мы определили поля bSaveBuffer и baos:

static byte[] bSaveBuffer;
ByteArrayOutputStream baos;

Первое из них хранит ссылку на массив байт, в который будет преобразовано содержимое выходного потока после завершения процесса записи, а второе - ссылку на выходной поток класса ByteArrayOutputStream.

Метод save класса DrawPanel

При сохранении изображения мы сначала создаем выходной поток в памяти как объект класса ByteArrayOutputStream:

baos = new ByteArrayOutputStream();

Этот поток мы будем использовать для записи объекта класса Vector, хранящего координаты нарисованных линий.

Для того чтобы записать в поток ByteArrayOutputStream объект класса Vector, мы создаем на базе этого потока поток класса ObjectOutputStream:

ObjectOutputStream oos;
     
try
{
  oos = new ObjectOutputStream(baos);
  oos.writeObject(lines);    
  oos.close();
      
  bSaveBuffer = baos.toByteArray();
}
catch (IOException ex)
{
  System.out.println(ex.toString());
}  

После создания потока ObjectOutputStream мы записываем в него вектор lines и закрываем поток методом close.

Далее данные потока сохраняются в массиве методом toByteArray. Этот метод динамически создает массив подходящего размера и возвращает ссылку на него. Мы сохраняем ссылку в поле bSaveBuffer, так как она будет нам нужна для восстановления объекта lines.

Метод restore класса DrawPanel

Восстановление нарисованного изображения выполняется методом restore.

Прежде всего этот метод создает новый поток ввода на базе массива bSaveBuffer:

ByteArrayInputStream bais;
bais = new ByteArrayInputStream(bSaveBuffer);

Этот поток размещается в оперативной памяти, а не привязан к файлу.

Далее на базе потока класса ByteArrayInputStream мы создаем поток ObjectInputStream и восстанавливаем из него содержимое объекта lines:

ObjectInputStream ois;
try
{
  ois = new ObjectInputStream(bais);
  lines = (Vector)ois.readObject();    
  ois.close();
}
catch (IOException ex)
{
  System.out.println(ex.toString());
}
catch (ClassNotFoundException ex)
{
  System.out.println(ex.toString());
}

После восстановления lines нам необходимо перерисовать окно аплета:

repaint(); 
Другие методы класса DrawPanel

Другие методы этого класса мы уже описывали в разделе "7.4. Сохранение объекта Java в файле".


Назад Вперед

[Назад]