Skip to content

Commit

Permalink
4. Архивировать проект. [#126243]
Browse files Browse the repository at this point in the history
Архивирует заданную директорию, сохраняя структуру проекта. В качестве ключей передаются расширения файлов, которые должны попасть в архив. Для просмотра каталога использован алгоритм обхода дерева в ширину.
  • Loading branch information
johnivo committed May 20, 2019
1 parent b495284 commit 036e12a
Show file tree
Hide file tree
Showing 5 changed files with 323 additions and 0 deletions.
114 changes: 114 additions & 0 deletions chapter_006/src/main/java/ru/job4j/io/zip/Args.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
package ru.job4j.io.zip;

import org.apache.commons.cli.*;
import java.util.ArrayList;
import java.util.List;

/**
* @author John Ivanov (johnivo@mail.ru)
* @since 15.05.2019
*/
public class Args {

/**
* Имя корня проекта.
*/
private String directory;

/**
* Список расширений файлов, которые игнорируются.
*/
private List<String> exclude = new ArrayList<>();

/**
* Имя файла архива.
*/
private String output;

/**
* Задаваемые параметры.
*/
private String[] args;


/**
* Конструктор.
*
* @param args задаваемые параметры
* -d - directory - которую мы ходим архивировать
* -e - exclude - исключить файлы *.xml
* -o - output - во что мы архивируем
*/
public Args(String[] args) throws ParseException {
this.args = args;
parser();
}

public String directory() {
return this.directory;
}

public List<String> exclude() {
return this.exclude;
}

public String output() {
return this.output;
}

/**
* Парсер командной строки.
*/
private void parser() {
// в options добавляем список опций
// "-d" короткая форма опции (однобуквенная опция), "directory" длинная форма опции,
// true флаг обозночающий наличие параметров и "directory" текстовое пояснение данной опции.
Options options = new Options();
CommandLineParser parser = new DefaultParser();
Option excludeOp = new Option("e", "exclude", true, "exclude extensions");
excludeOp.setArgs(Option.UNLIMITED_VALUES);
excludeOp.setValueSeparator(' ');
options.addOption(excludeOp);
options.addOption("d", "directory", true, "directory that must be archived");
options.addOption("o", "output", true, "output archive file");

try {
CommandLine commandLine = parser.parse(options, args);

if (commandLine.hasOption("d")) {
System.out.print("Option d is present. The value is: ");
System.out.println(commandLine.getOptionValue("d"));
String arguments = commandLine.getOptionValue("d");
this.directory = arguments;
}

if (commandLine.hasOption("e")) {
System.out.print("Option e is present. The value is: ");
System.out.println(List.of(commandLine.getOptionValues("e")));
String[] arguments = commandLine.getOptionValues("e");
for (String s : arguments) {
this.exclude.add(s);
}
}

if (commandLine.hasOption("o")) {
System.out.print("Option o is present. The value is: ");
System.out.println(commandLine.getOptionValue("o"));
String arguments = commandLine.getOptionValue("o");
this.output = arguments;
}

String[] remainder = commandLine.getArgs();
System.out.print("Remaining arguments: ");
for (String argument : remainder) {
System.out.print(argument);
System.out.print(" ");
}
System.out.println();

} catch (ParseException pe) {
System.out.print("Parse error: ");
System.out.println(pe.getMessage());
}
}
}
24 changes: 24 additions & 0 deletions chapter_006/src/main/java/ru/job4j/io/zip/MainZip.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package ru.job4j.io.zip;

import org.apache.commons.cli.ParseException;

import java.io.IOException;

/**
* Точка входа в программу-архиватор.
*
* @author John Ivanov (johnivo@mail.ru)
* @since 17.05.2019
*/
public class MainZip {

public static void main(String[] args) throws ParseException {
Zip zip = new Zip();
Args keys = new Args(args);
try {
zip.pack(keys);
} catch (IOException e) {
e.printStackTrace();
}
}
}
82 changes: 82 additions & 0 deletions chapter_006/src/main/java/ru/job4j/io/zip/Zip.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
package ru.job4j.io.zip;

import org.apache.commons.cli.ParseException;

import java.io.*;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

/**
* Архиватор проекта.
*
* @author John Ivanov (johnivo@mail.ru)
* @since 15.05.2019
*/
public class Zip {

/**
* Архивирует проект, сохраняя структуру каталогов.
*
* @param args входящие параметры.
*/
public void pack(Args args) throws IOException {
List<File> list = seekBy(args.directory(), args.exclude());
try (ZipOutputStream zos =
new ZipOutputStream(
new BufferedOutputStream(
new FileOutputStream(args.output(), false)
)
)
) {
for (File file : list) {
zos.putNextEntry(new ZipEntry(file.getAbsolutePath().substring(args.directory().length() + 1)));
try (BufferedInputStream out =
new BufferedInputStream(
new FileInputStream(file)
)
) {
zos.write(out.readAllBytes());
} catch (IOException ioe) {
ioe.printStackTrace();
}
}
} catch (IOException ioe) {
ioe.printStackTrace();
}
}

/**
* Сканирует содержимое заданного каталога, в т.ч. все вложенные папки и
* возвращает список файлов за исключением списка игнора.
*
* @param parent путь до каталога, в котором нужно осуществлять поиск.
* @param exts список игнорируемых расширений файлов.
* @return list список файлов.
*/
public List<File> seekBy(String parent, List<String> exts) {
List<File> rsl = new ArrayList();
File file = new File(parent);
Queue<File> data = new LinkedList<>();
data.offer(file);
while (!data.isEmpty()) {
File el = data.poll();
if (!el.isDirectory()) {
String name = el.getName();
if (name.contains(".")) {
if (!exts.contains(name.substring(name.indexOf(".")))) {
rsl.add(el);
}
}
} else {
for (File child : el.listFiles()) {
data.offer(child);
}
}
}
return rsl;
}
}
96 changes: 96 additions & 0 deletions chapter_006/src/test/java/ru/job4j/io/zip/ZipTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
package ru.job4j.io.zip;

import org.junit.Test;

import java.io.File;
import java.io.IOException;
import org.apache.commons.cli.ParseException;

import java.util.Arrays;

import static org.hamcrest.core.Is.is;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertThat;

/**
* @author John Ivanov (johnivo@mail.ru)
* @since 16.05.2019
*/
public class ZipTest {

/**
* Parsing test.
*/
@Test
public void whenArgsAddThenAllExistsAsOption() throws ParseException {
String[] args = {
"-d",
"c:/Users/Barclay/AppData/Local/Temp/project",
"-e",
".java", ".xml", ".dll",
"-o",
"test.zip",
"other"
};
Args keys = new Args(args);
assertThat(keys.directory(), is("c:/Users/Barclay/AppData/Local/Temp/project"));
assertThat(keys.output(), is("test.zip"));
assertEquals(keys.exclude(), Arrays.asList(".java", ".xml", ".dll"));
assertThat(keys.exclude(), is(Arrays.asList(".java", ".xml", ".dll")));
}

/**
* Archiving test.
*/
@Test
public void whenDirectoryPackInZipThenTestZipFileIsCreated2() throws IOException, ParseException {
File project = new File(
System.getProperty("java.io.tmpdir")
+ System.getProperty("file.separator")
+ "project"
);
project.mkdirs();
new File(project + "/file0.csv").createNewFile();
new File(project + "/qwerty").mkdirs();
new File(project + "/dir1").mkdirs();
new File(project + "/dir1/file1.csv").createNewFile();
new File(project + "/dir2").mkdirs();
new File(project + "/dir2/file2.xml").createNewFile();
new File(project + "/dir1/dir3").mkdirs();
new File(project + "/dir1/dir3/file3.txt").createNewFile();
new File(project + "/dir1/dir3/file4.xml").createNewFile();
String[] args = {
"-d",
project.getAbsolutePath(),
"-e",
".xml", ".txt",
"-o",
"test.zip"
};
Args keys = new Args(args);
Zip zip = new Zip();
zip.pack(keys);
File[] files = new File(System.getProperty("user.dir")).listFiles(
file -> file.getName().equals(keys.output())
);
assertThat(files.length, is(1));
assertThat(files[0].exists(), is(true));
files[0].deleteOnExit();
recursiveDelete(project);
}

/**
* Delete data.
* @param file directory name.
*/
public static void recursiveDelete(File file) {
if (file.exists()) {
if (file.isDirectory()) {
for (File f : file.listFiles()) {
recursiveDelete(f);
}
}
file.delete();
}
}
}
7 changes: 7 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,13 @@
<artifactId>javafx-base</artifactId>
<version>11</version>
</dependency>

<!-- https://mvnrepository.com/artifact/commons-cli/commons-cli -->
<dependency>
<groupId>commons-cli</groupId>
<artifactId>commons-cli</artifactId>
<version>1.4</version>
</dependency>

</dependencies>

Expand Down

0 comments on commit 036e12a

Please sign in to comment.