Назад
Вперед
7.25. Вычисление контрольной суммы файла
В примере демонстрируется использование
библиотеки классов java.util.zip для вычиления
контрольной суммы файла по методам CRC-32 и Adler-32.
Исходный текст примера
Архив проекта для Java WorkShop 2.0
Немного теории
Иногда перед программистом встает задача
вычисления контрольной суммы файла. Такая сумма
может потребоваться, например, чтобы убедиться в
сохранности файла при его передаче по сети или
при его хранении в небезопасных условиях.
Разумеется, вы можете сами организовать
подсчет контрольной суммы, например, просто
складывая последовательности четырехбайтовых
слов по модулю два или с применением какого-либо
иного алгоритма.
В библиотеке классов java.util.zip есть классы и
интерфейсы, намного упрощающие данную задачу.
Это классы CRC32, Adler32 и интерфейс Checksum.
Интерфейс Checksum
Интерфейс Checksum определяет методы,
применяющиеся при подсчете контрольной суммы.
Это методы update, getValue и reset.
Метод update существует в виде двух реализаций:
public abstract void update(int b);
public abstract void update(byte b[],
int off, int len);
Первая из них обновляет контрольную сумму
значением одного байта, а вторая - значениями
массива байт.
Метод getValue возвращает текущее значение
контрольной суммы:
public abstract long getValue();
Метод reset сбрасывает значение контрольной
суммы в исходное состояние:
public abstract void reset();
Классы CRC32 и Adler32
Классы CRC32 и Adler32 предоставляют в ваше
распоряжение две различные готовые реализации
интерфейса Checksum, использующие 32-разрядное
суммирование. Первый из них реализует алгоритм
CRC-32, а второй - Adler-32 (более быстродействующий).
Для того чтобы организовать в своем приложении
вычисление контрольной суммы файла с
применением классов CRC32 или Adler32, вам вначале
нужно создать объект одного из этих классов,
воспользовавшись для этого соответствующим
конструктором. Заметим, что конструкторы этих
классов не имеют параметров.
Далее вам нужно создать входной поток для
исследуемого файла и организовать его чтение
блоками в цикле. На каждой итерации цикла вы
должны вызывать метод update класса CRC32 или Adler32.
После завершения цикла искомая контрольная
сумма может быть получена методом getValue,
определенным в этих классах.
Описание примера
Наше приложение позволяет выбирать файлы с
помощью стандартной диалоговой панели класса
FileDialog, определяя для них контрольные суммы с
применением алгоритмов CRC-32 и Adler-32.
Путь к файлу и значения контрольных сумм
отображаются в окне многострочного редактора
текста, расположенного в главном окне приложения
(рис. 1).
Рис. 1. Просмотр контрольных сумм файлов
Рассмотрим наиболее важные фрагменты
исходного текста приложения.
Когда пользователь выбирает из меню File строку
Open, управление передается методу actionPerformed.
Данный метод создает и отображает на экране
диалоговую панель выбора входного файла,
получает путь к выбранному пользователем файлу,
сохраняет его в переменной szPath и показывает в
окне приложения:
if(e.getSource().equals(miOpen))
{
fdlg = new FileDialog(this, "Open file",
FileDialog.LOAD);
fdlg.show();
String szPath = fdlg.getDirectory() +
fdlg.getFile();
ta.append("Open: " + szPath + "\n");
. . .
}
Далее мы два раза вызываем метод calculate,
определенный в нашем приложении, который
возвращает текстовое представление значения
контрольной суммы:
ta.append("CRC-32: " +
calculate(szPath, new CRC32()) + "\n");
ta.append("Adler-32: " +
calculate(szPath, new Adler32()) + "\n");
Через первый параметр этому методу передается
путь к файлу, а через второй - ссылка на класс,
определяющий метод вычисления контрольной
суммы.
Как устроен метод calculate?
Прежде всего этот метод открывает входной
поток для файла, контрольную сумму которого
необходимо вычислить:
String s = "";
byte[] buf = new byte[8000];
int nLength = 0;
try
{
FileInputStream fis =
new FileInputStream(szPath);
. . .
}
Далее мы организуем чтение из потока в цикле
блоками по 8000 байт (значение, выбранное нами
произвольно), с периодическим обновлением
контрольной суммы методом update:
while(true)
{
nLength = fis.read(buf);
if(nLength < 0)
break;
cs.update(buf, 0, nLength);
}
После достижения конца файла связанный с ним
поток закрывается, а значение контрольной суммы
извлекается методом getValue:
fis.close();
. . .
s = new Long(cs.getValue()).toString();
return s;
Мы преобразуем его в текстовую строку класса
String и возвращаем вызвавшему методу.
Назад Вперед |