Progress-servis55.ru

Новости из мира ПК
2 просмотров
Рейтинг статьи
1 звезда2 звезды3 звезды4 звезды5 звезд
Загрузка...

Java util zip

Работа с архивами Zip и 7z

В мобильной разработке бывает потребность сделать приложение для работы без интернета. Например, словарь или справочник, который будет использоваться в суровых полевых условиях. Тогда для работы приложения нужно единожды выкачать архив с данными и сохранить его у себя. Сделать это можно посредством запроса в сеть, но так же можно зашить архив с данными внутрь приложения.

Согласно требованиям Google Play, apk-файл приложения должен быть не более 50 МБ, так же можно прикрепить два файла дополнения .obb по 2 гигабайта. Механизм простой, но сложный при эксплуатации, поэтому лучше всего уложиться в 50 МБ и возрадоваться. И в этом нам помогут целых два архивных формата Zip и 7z.

Давайте рассмотрим их работу на примере уже готового тестового приложения ZipExample.

Для тестов была создана sqlite база данных test_data.db. Она содержит 2 таблицы android_metadata — по традиции и my_test_data с миллионом строчек:

Размер полученного файла составляет 198 МБ.

Сделаем два архива test_data.zip (10.1 МБ) и test_data.7z (3.05 МБ).

Как очевидно, файлы БД sqlite очень хорошо сжимаются. По опыту могу сказать, что чем проще структура базы, тем лучше сжимается. Оба этих файла располагаются в папке assets и в процессе работы будут разархивированы.

Внешний вид программы представляет собой окно с текстом и двумя кнопками:

Вот метод распаковки zip архива:

Распаковывающим классом тут является ZipInputStream он входит в пакет java.util.zip, а тот в свою очередь в стандартную Android SDK и поэтому работает «из коробки» т.е. ничего отдельно закачивать не надо.

Вот метод распаковки 7z архива:

Сначала мы копируем файл архива из asserts , а потом разархивируем при помощи SevenZFile . Он находится в пакете org.apache.commons.compress.archivers.sevenz; и поэтому перед его использованием нужно прописать в build.gradle зависимость: compile ‘org.apache.commons:commons-compress:1.8’.
Android Stuodio сама скачает библиотеки, а если они устарели, то подскажет о наличии обновления.

Вот экран работающего приложения:

Размер отладочной версии приложения получился 6,8 МБ.
А вот его размер в устройстве после распаковки:

Внимание вопрос кто в черном ящике что в кеше?

Читать еще:  Предельная ошибка выборки равна

В заключении хочу сказать, что распаковка архивов занимает продолжительное время и поэтому нельзя его делать в основном (UI) потоке. Это приведет к подвисанию интерфейса. Во избежание этого можно задействовать AsyncTask , а лучше фоновый сервис т.к. пользователь может не дождаться распаковки и выйти, а вы получите ошибку (правда если не поставите костылей в методе onPostExecute).

Буду рад конструктивной критике в комментариях.

Zip-архивирование в Java

категория
Java
дата05.08.2010
авторwisd
голосов9

Считывание содержимого Zip-архива.

В Java для чтения Zip-архивов применяется класс ZipInputStream. В каждом таком архиве всегда требуется просматривать отдельные записи (entries). Метод getNextEntry возвращает описывающий запись объект типа ZipEntry. Метод read класса ZipInputStream изменяется так, чтобы он возвращал -1 в конце текущей записи (а не просто в конце Zip-файла). Далее вызывается метод closeEntry для получения возможности перехода к считыванию следующей записи.

ZipInputStream zin = new ZipInputStream(new FileInputStream(zipName));
ZipEntry entry;
while ((entry = zin.getNextEntry()) != null) <
//анализ entry
//считывание содежимого
zin.closeEntry();
>
zin.close();

Для считывания содержимого конкретной записи из Zip-файла эффективнее использовать не стандартный метод read, а методы какого-то обладающего большими возможностями потокового фильтра. Например, для считывания текстового файла, находящегося внутри Zip-архива, можно применить следующий цикл:

Scanner in = new Scanner(zin);
while (in.hasNextLine()) <
//выполнение операций с in.nextLine()

Запись в Zip-архив.

Для записи Zip-файла применяется класс ZipOutputStream. Для каждой записи, которую требуется поместить в Zip-файл, создается объект ZipEntry. Желаемое имя для файла передается конструктору ZipEntry; тот устанавливает устанавливает остальные параметры, вроде даты создания файла и метода распаковки. При желании эти параметры могут переопределяться. Далее вызывается метод putNextEntry класса ZipOutputStream для начала процесса записи нового файла. После этого данные самого файла отправляются потоку ZIp. По завершении вызывается метод closeEntry. Затем все эти действия выполняются повторно для всех остальных файлов, которые требуется сохранить в Zip-архиве. Ниже приведена общая схема необходимого кода:

FileOutputStream fout = new FileOutputStream(«test.zip»);
ZipOutputStream zout = new ZipoutputStream(fout);
//Для всех файлов:
<
ZipEntry ze = new ZupEntry(«имя файла»);//Имя файла — имя файла в архиве
zout.putNextEntry(ze);
//отправка данных в поток zout
zout.closeEntry();
>
zout.close();

Читать еще:  Интерфейс cloneable java

Сжатие объектов с сохранением

Имеется класс «Работник» реализующий интерфейс для сериализации:

public class Employee implements Serializable <

String name;
int age;
int salary;

public Employee(String name, int age, int salary) <
this.name = name;
this.age = age;
this.salary = salary;
>

public void print() <
System.out.println(«Record for: » + name);
System.out.println(«Name: » + name);
System.out.println(«Age: » + age);
System.out.println(«Salary: » + salary);
>
>

Сохранить объекты данного класса мы можем следующим кодом:

import java.io.*;
import java.util.zip.*;

public class SaveEmployee <

public static void main(String argv[]) throws
Exception <
Employee sarah = new Employee(«S. Jordan», 28,
56000);
Employee sam = new Employee(«S. McDonald», 29,
58000);
FileOutputStream fos = new FileOutputStream(«db»);
GZIPOutputStream gz = new GZIPOutputStream(fos);
ObjectOutputStream oos = new ObjectOutputStream(gz);
oos.writeObject(sarah);
oos.writeObject(sam);
oos.flush();
oos.close();
fos.close();
>
>

Здесь всё просто, данные мы сохраняем в файл (FileOutputStream) перед этим сжав их (GZIPOutputStream), а в роли данных выступают объекты (ObjectOutputStream).

Загрузить сохраненные сжатые объекты также просто как и сохранить их:

import java.io.*;
import java.util.zip.*;

public class ReadEmployee <

public static void main(String argv[]) throws
Exception <
FileInputStream fis = new FileInputStream(«db»);
GZIPInputStream gs = new GZIPInputStream(fis);
ObjectInputStream ois = new ObjectInputStream(gs);
Employee sarah = (Employee) ois.readObject();
Employee sam = (Employee) ois.readObject();
sarah.print();
sam.print();
ois.close();
fis.close();
>
>

Данные считываются из файла (FileInputStream), файлы являются сжатыми (GZIPInputStream), данными являются объекты (ObjectInputStream).

Также можно обмениваться сжатыми объектами между сервером/клиентом (с использованием сокетов), ниже представлен код отправки сжатого объекта клиенту:

GZIPOutputStream gzipout =
new GZIPOutputStream(socket.getOutputStream());
ObjectOutputStream oos =
new ObjectOutputStream(gzipout);
oos.writeObject(obj);
gzipos.finish();

Ниже представлен код по получению и декомпрессии данных объекта от сервера:

Socket socket = new Socket(remoteServerIP, PORT);
GZIPInputStream gzipin =
new GZIPInputStream(socket.getInputStream());
ObjectInputStream ois = new ObjectInputStream(gzipin);
Object o = ois.readObject();

Если Вам понравилась статья, проголосуйте за нее

Голосов: 9 Голосовать

Учимся программировать на Java с нуля

ZIP-архивы в языке Java

ZIP-архивы позволяют хранить один и более файлов в (обычно) сжатом формате. У каждого ZIP-архива имеется заголовок, содеражащий информацию вроде имени файла или использовавшегося для него метода сжатия. В Java для чтения ZIP-архивов применяется класс ZipInputStream. В каждом таком архиве всегда требуется просматривать отдельные записи(entries).

Метод getNextEntry возвращает описывающий запись объект типа ZipEntry. Метод read класс ZipInputStream изменяется так, чтобы он возвращал -1 в конце текущий записи(а не просто в конце ZIP-файла).

Читать еще:  Создать приложение java

Далее вызывается метод closeEntry для получения возможности перехода к считыванию следующей записи. Ниже приведена типичная кодовая последовательность для выполнения считывания содержимого ZIP-файла:

Для считывания содержимого конкретной записи из ZIP-файла эффективнее использовать не стандартный метод read, а методы какого-то обладающего большими находящегося внутри ZIP-архива, можно применить следующий цикл:

В случае возникновения ошибки при считывании ZIP-файла класс ZipInputStream выдает исключение ZipException. Обычно подобное происходит при повреждении ZIP-файла.

Для записи ZIP-файла применяется класс ZipOutputStream. Для каждой записи, которую требуется поместить в ZIP-файл, создается объект ZipEntry. Желаемое имя для файла передается конструктору ZipEntry, тот устанавливает остальные параметры, вроде даты создания файла и метода распаковки.

При желании эти параметры могут переопределяться. Далее вызывается метод putNextEntry класса ZipOutputStream для начала процесса записи нового файла. После этого данные самого файла отправляются потоку ZIP. По завершении вызывается метод closeEntry. Затем все эти действия выполняются повторно для всех остальных файлов, которые требуется сохранить в ZIP-архиве. Ниже приведена общая схема необходимого кода:

JAR-файлы представляют собой те же ZIP-файлы, но только содержат записи несколько иного вида, называемые манифестом. Для считывания и записи манифестов применяются классы JarInputStream и JarOutputStream.

ZIP-потоки являются прекрасным примером мощи потоковой абстракции. При считывании данных, которые хранятся в сжатом виде, не нужно волноваться о том, будут ли они распаковаться по мере запрашивания. И источником байтов в ZIP-форматах вовсе не обязательно должен быть именно файл: ZIP-данные могут поступать и через сетевое подключение. На самом деле, при всяком считывании JAR-файла загрузчик классов аплета будет считывать и распаковывать данные именно из сети.

Рис.2. Программа ZipTest

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

Ссылка на основную публикацию
Adblock
detector