KnigaRead.com/

Брюс Эккель - Философия Java3

На нашем сайте KnigaRead.com Вы можете абсолютно бесплатно читать книгу онлайн Брюс Эккель, "Философия Java3" бесплатно, без регистрации.
Перейти на страницу:

//: io/Fi1eLocking.java import java.nio.channels.*; import java.util.concurrent.*; import java.io.*;

public class FileLocking {

public static void main(String[] args) throws Exception {

FileOutputStream fos= new FileOutputStreamCfile txt");

FileLock fl = fos.getChannel О .tryLockO.

if(fl != null) {

System.out.println("Файл заблокирован"); Ti meUnit.MILLISECONDS.sieep(100); fl .releaseO;

System ои^ргШ1п("Блокировка снята"),

}

fos.closeO;

}

} /* Output; Файл заблокирован Блокировка снята *///:-

Блокировать файл целиком позволяет объект FileLock, который вы получаете, вызывая метод tryLock() или lock() класса FileChannel. (Сетевые каналы Socket-Channel, DatagramChannel и ServerSocketChannel не нуждаются в блокировании, так как они доступны в пределах одного процесса. Вряд ли сокет будет использоваться двумя процессами совместно.) Метод tryLock() не приостанавливает программу. Он пытается овладеть объектом блокировки, но если ему это не удается (если другой процесс уже владеет этим объектом или файл не является разделяемым), то он просто возвращает управление. Метод lockQ ждет до тех пор, пока не удастся получить объект блокировки, или поток, в котором этот метод был вызван, не будет прерван, или же пока не будет закрыт канал, для которого был вызван метод lock(). Блокировка снимается методом FileChannel. release().

Также можно заблокировать часть файла вызовом

tryLockdong position, long size, boolean shared) или

lockdong position, long size, boolean shared)

Блокируется участок файла размером size от позиции position. Третий аргумент указывает, будет ли блокировка совместной.

Методы без аргументов приспосабливаются к изменению размеров файла, в то время как методы для блокировки участков не адаптируются к новому размеру файла. Если блокировка была наложена на область от позиции position до position + size, а затем файл увеличился и стал больше размера position + size, то часть файла за пределами position + size не блокируется. Методы без аргументов блокируют файл целиком, даже если он растет.

Поддержка блокировок с эксклюзивным или разделяемым доступом должна быть встроена в операционную систему. Если операционная система не поддерживает разделяемые блокировки и был сделан запрос на получение такой блокировки, используется эксклюзивный доступ. Тип блокировки (разделяемая или эксклюзивная) можно узнать при помощи метода FileLock.isShared().

Блокирование части отображаемого файла

Как уже было упомянуто, отображение файлов обычно используется для файлов очень больших размеров. Иногда при работе с таким большим файлом требуется заблокировать некоторые его части, в то время как доступные части будут изменяться другими процессами. В частности, такой подход характерен для баз данных, чтобы несколько пользователей могли работать с базой одновременно.

В следующем примере каждый их двух потоков блокирует свою собственную часть файла:

//: 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

Интерфейс сжатия данных в формате GZIP является наиболее простым и идеально подходит для ситуаций, где имеется один поток данных, который необходимо уплотнить (а не разрозненные фрагменты данных). В следующем примере сжимается файл:

// io/GZIPcompress java // {Параметры- GZIPcompress.java} import java util zip *, import java io *.

public class GZIPcompress {

public static void main(String[] args)

throws IOException { продолжение &

if(args.length == 0) {

System out.printlnC

"Использование: nGZIPcompress filen" + "иИспользует метод GZIP для сжатия " + "файла в архив test.gz"); System.exit(l),

}

BufferedReader in = new BufferedReader( new FileReader(args[0])),

BufferedOutputStream out = new BufferedOutputStrearrK new GZIPOutputStreamC

new FileOutputStreamC'test gz"))),

System.out.println("3anncb файла");

int с;

while((c = in.readO) != -1) out.write(c);

in.closeO;

out.closeO;

System.out.printlnC"Чтение файла");

BufferedReader in2 = new BufferedReader(

new InputStreamReader(new GZIPInputStreamC new FilelnputStreamC'test gz")))).

String s;

while((s = in2 readLineO) != null) System.out.printin(s);

}

} ///:-

Работать с классами сжатия данных очень просто: вы просто надстраиваете их для своего потока данных (GZIPOutputStream или ZipOutputStream для сжатия, GZIPInputStream или ZipInputStream для распаковки данных). Дальнейшее сводится к элементарным операциям ввода/вывода. В примере продемонстрированы смешанные байтовые и символьные потоки: поток in основан на Reader, тогда как конструктор класса GZIPOutputStream использует только потоки на основе OutputStream, но не Writer. Поэтому при открытии файла поток GZIPInputStream преобразуется в символьный поток Reader.

Многофайловые архивы ZIP

Библиотека, поддерживающая формат сжатия данных ZIP, обладает гораздо более широкими возможностями. С ее помощью можно легко упаковывать произвольное количество файлов, а для чтения файлов в формате ZIP даже определен отдельный класс. В библиотеке поддержан стандартный ZIP-формат, поэтому сжатые ею данные будут восприниматься практически любым упаковщиком. Структура следующего примера совпадает со структурой предыдущего, но количество файлов, указываемых в командной строке, не ограничено. Вдобавок демонстрируется применение класса Checksum для получения и проверки контрольной суммы. Таких типов контрольных сумм в Java два: один представлен классом АсИег32'(этот алгоритм быстрее), а другой — классом CRC32 (медленнее, но точнее).

//: io/ZipCompress.java

// Использование формата ZIP для сжатия любого

// количества файлов, указанных в командной строке.

// {Параметры. ZipCompress java}

import java.util zip *;

import java io *;

import java.util *,

import static net mindview.util Print *,

public class ZipCompress {

public static void mainCString[] args) throws IOException {

FileOutputStream f = new FileOutputStreamC'test zip"). CheckedOutputStream csum =

new CheckedOutputStream(f. new Adler320). ZipOutputStream zos = new ZipOutputStream(csum). BufferedOutputStream out =

new BufferedOutputStream(zos). zos setComment("Проверка ZIP-сжатия Java"). // Однако парного метода для получения комментария // getCommentO не существует for(String arg . args) {

print("3anncb файла " + arg). BufferedReader in =

Перейти на страницу:
Прокомментировать
Подтвердите что вы не робот:*