-
Notifications
You must be signed in to change notification settings - Fork 41
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Архивирует заданную директорию, сохраняя структуру проекта. В качестве ключей передаются расширения файлов, которые должны попасть в архив. Для просмотра каталога использован алгоритм обхода дерева в ширину.
- Loading branch information
Showing
5 changed files
with
323 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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()); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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(); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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(); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters