Как уже было упомянуто, отображение файлов обычно используется для файлов очень больших размеров. Иногда при работе с таким большим файлом требуется заблокировать некоторые его части, в то время как доступные части будут изменяться другими процессами. В частности, такой подход характерен для баз данных, чтобы несколько пользователей могли работать с базой одновременно.
В следующем примере каждый их двух потоков блокирует свою собственную часть файла:
//: io/LockingMappedFiles.java
// Блокирование части отображаемого файла
// {RunByHand}
import java.nio *,
import java nio channels *,
import java io *,
public class LockingMappedFiles {
static final int LENGTH = Ox8FFFFFF; // 128 MB static FileChannel fc;
public static void main(String[] args) throws Exception { fc =
new RandomAccessFileC'test.dat", "rw").getChannel0; MappedByteBuffer out =
fc.map(Fi1eChannel.MapMode.READ_WRITE, 0. LENGTH); for(int i = 0; i < LENGTH; i++)
out.put((byte)'x'); new LockAndModify(out. 0, 0 + LENGTH/3); new LockAndModify(out, LENGTH/2, LENGTH/2 + LENGTH/4);
}
private static class LockAndModify extends Thread { private ByteBuffer buff; private int start, end;
LockAndModify(ByteBuffer mbb. int start, int end) { this.start = start; this.end = end; mbb.limit(end); mbb.position(start); buff = mbb.sliceO; startO;
}
public void runО { try {
// Монопольная блокировка без перекрытия;
FileLock fl = fc.lock(start, end, false);
System.out.println("Заблокировано: "+ start +" to "+ end);
// Модификация:
while(buff.position() < buff.limitO - 1) buff.put((byte)(buff.get О + 1)); fl.releasee);
System.out.println("Освобождено: "+start+" to "+ end); } catch(IOException e) {
throw new RuntimeException(e);
}
}
}
} ///:-
Класс потока LockAndModify устанавливает область буфера и получает его для модификации методом slice(). В методе run() для файлового канала устанавливается блокировка (вы не вправе запросить блокировку для буфера, это позволено только для канала). Вызов lock() напоминает механизм синхронизации доступа потоков к объектам, у вас появляется некая «критическая секция» с монопольным доступом к данной части файла.
Блокировки автоматически снимаются при завершении работы JVM, закрытии канала, для которого они были получены, но можно также явно вызвать метод releaseQ объекта FileLock, что здесь и показано.
Сжатие данных
Библиотека ввода/вывода Java содержит классы, поддерживающие ввод/вывод в сжатом формате (табл. 16.8). Они базируюся на уже существующих потоках ввода/вывода.
Эти классы не являются частью иерархии символьно-ориентированных потоков Reader и Writer, они надстроены над байт-ориентированными классами InputStream и OutputStream, так как библиотека сжатия работает не с символами, а с байтами. Впрочем, никто не запрещает смешивать потоки. (Помните, как легко преобразовать потоки из байтовых в символьные — достаточно использовать классы InputStreamReader и OutputStreamWriter.)
Таблица 16.8. Классы для сжатия данных
Назначение
CheckedlnputStream
CheckedOutputStream
DeflaterOutputStream ZipOutputStream
GZIPOutputStream
InflaterlnputStream ZipInputStream
GZIPInputStream
Название класса
Его метод getCheckSum() возвращает контрольную сумму для любого входного потока InputStream (не только для потока распаковки) Его метод getCheckSum() возвращает контрольную сумму для любого выходного потока OutputStream (не только для потока сжатия) Базовый класс для классов сжатия данных
Подкласс DeflaterOutputStream, который производит сжатие данных в формате файлов ZIP
Подкласс DeflaterOutputStream, который производит сжатие данных в формате файлов GZIP
Базовый класс для классов распаковки сжатых данных
Подкласс InflaterlnputStream, который распаковывает сжатые данные,
хранящиеся в формате файлов ZIP
Подкласс InflaterlnputStream, распаковывающий сжатые данные, хранящиеся в формате файлов GZIP
Хотя существует великое количество различных программ сжатия данных, форматы ZIP и GZIP используются, пожалуй, чаще всего. Таким образом, вы можете легко манипулировать своими сжатыми данными с помощью многочисленных программ, предназначенных для чтения и записи этих форматов.
Простое сжатие в формате GZIP