先日、tar and gzip 圧縮・展開を書いたので、ZIP圧縮・展開です。これは Apache commons-compress を必要とすることなく
標準ライブラリと、Throwable な Consumerがあれば綺麗に書けます。→ ラムダ式の例外処理を綺麗にする - Oboe吹きプログラマの黙示録
圧縮サンプル ・・・Throwable な Consumer → ThrowableConsumer.of を使います。
List<String> files =
try(ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(new File("out/test.zip")))){
files.stream().forEach(ThrowableConsumer.of(e->{
File f = new File(e);
if (f.exists()){
zos.putNextEntry(new ZipEntry(f.isDirectory() ? e + "/" : e));
if (f.isFile()){
try(FileInputStream fis = new FileInputStream(e); BufferedInputStream bis = new BufferedInputStream(fis)){
int size = 0;
byte[] buf = new byte[1024];
while((size = bis.read(buf)) > 0){
zos.write(buf, 0, size);
}
}
}
}
}));
}catch(Exception ex){
ex.printStackTrace();
}
展開サンプル、展開時にエントリ名を標準出力してます。
try(ZipInputStream zin = new ZipInputStream(new FileInputStream("out/test.zip"))){
ZipEntry entry;
while((entry = zin.getNextEntry()) != null){
System.out.println( entry.getName() );
if (entry.isDirectory()){
String s = entry.getName();
new File(dirPath + "/" + s.substring(0, s.length()-1)).mkdir();
}else{
String[] d = entry.getName().split("/");
String dir = dirPath;
for(int i=0;i < d.length-1;i++){
dir += "/" + d[i];
new File(dir).mkdir();
}
try(FileOutputStream fos = new FileOutputStream(dirPath+"/"+entry.getName()); BufferedOutputStream bos = new BufferedOutputStream(fos)){
int size = 0;
byte[] buf = new byte[1024];
while((size = zin.read(buf)) > 0){
bos.write(buf, 0, size);
}
}
}
}
}catch(Exception ex){
ex.printStackTrace();
}
tar and gzip のケースのように、
tar and gzip 圧縮・展開を補強 - Oboe吹きプログラマの黙示録
ディレクトリscan を合わせて、
oboe2uran.hatenablog.com
1つのインターフェースとしてまとめておきたくなりました。
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Set;
import java.util.TreeSet;
import java.util.function.Predicate;
import java.util.function.Supplier;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import java.util.zip.ZipOutputStream;
import org.yipuran.function.ThrowableConsumer;
ZIP 圧縮/解凍プロセッサ.
<Collection<FileCollection>>
<String>
@since 1.1
public interface ZipProcessor extends Supplier<Collection<FileCollection>>{
ZIP 圧縮実行.
<PRE>
<FileCollection>
>
>
<String>
>
<String>
</PRE>
@param zipPath
@return
public default Collection<String> compress(String zipPath){
Collection<String> entries = new ArrayList<>();
try(ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(new File(zipPath)))){
get().forEach(fc->{
String prefix = fc.getFile().getParentFile().getAbsolutePath().replaceAll("\\\\", "/");
fc.scan(ThrowableConsumer.of(f->{
String entryName = f.getAbsolutePath().replaceAll("\\\\", "/").replaceFirst(prefix, "");
ZipEntry entry = new ZipEntry(f.isDirectory() ? entryName + "/" : entryName);
entries.add(entry.getName().charAt(0)=='/' ? entry.getName().substring(1) : entry.getName());
zos.putNextEntry(entry);
if (f.isFile()){
try(FileInputStream fis = new FileInputStream(f); BufferedInputStream bis = new BufferedInputStream(fis)){
int size = 0;
byte[] buf = new byte[1024];
while((size = bis.read(buf)) > 0){
zos.write(buf, 0, size);
}
}
}
}));
});
}catch(IOException ex){
throw new RuntimeException(ex);
}
return entries;
}
zip 圧縮実行(対象制限).
<PRE>
<File>
</PRE>
@param zipPath
@param p<File>
@return
public default Collection<String> compress(String zipPath, Predicate<File> p){
Collection<String> entries = new ArrayList<>();
try(ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(new File(zipPath)))){
get().forEach(fc->{
String prefix = fc.getFile().getParentFile().getAbsolutePath().replaceAll("\\\\", "/");
fc.scan(p, ThrowableConsumer.of(f->{
String entryName = f.getAbsolutePath().replaceAll("\\\\", "/").replaceFirst(prefix, "");
ZipEntry entry = new ZipEntry(f.isDirectory() ? entryName + "/" : entryName);
entries.add(entry.getName().charAt(0)=='/' ? entry.getName().substring(1) : entry.getName());
zos.putNextEntry(entry);
if (f.isFile()){
try(FileInputStream fis = new FileInputStream(f); BufferedInputStream bis = new BufferedInputStream(fis)){
int size = 0;
byte[] buf = new byte[1024];
while((size = bis.read(buf)) > 0){
zos.write(buf, 0, size);
}
}
}
}));
});
}catch(IOException ex){
throw new RuntimeException(ex);
}
return entries;
}
ZIPファイル展開.
@param zipPath
@param dirPath
@return<String>
public static Set<String> decompress(String zipPath, String dirPath){
TreeSet<String> entries = new TreeSet<>();
try(ZipInputStream zin = new ZipInputStream(new FileInputStream(zipPath))){
ZipEntry entry;
while((entry = zin.getNextEntry()) != null){
entries.add(entry.getName());
if (entry.isDirectory()){
String s = entry.getName();
new File(dirPath + "/" + s.substring(0, s.length()-1)).mkdir();
}else{
String[] d = entry.getName().split("/");
String dir = dirPath;
for(int i=0;i < d.length-1;i++){
dir += "/" + d[i];
new File(dir).mkdir();
}
try(FileOutputStream fos = new FileOutputStream(dirPath+"/"+entry.getName()); BufferedOutputStream bos = new BufferedOutputStream(fos)){
int size = 0;
byte[] buf = new byte[1024];
while((size = zin.read(buf)) > 0){
bos.write(buf, 0, size);
}
}
}
}
}catch(IOException ex){
throw new RuntimeException(ex.getMessage(), ex);
}
return entries;
}
エントリ名コレクション.
@param zipPath
@return<String>
public static Set<String> viewPath(String zipPath){
TreeSet<String> entries = new TreeSet<>();
try(ZipInputStream zin = new ZipInputStream(new FileInputStream(zipPath))){
ZipEntry entry;
while((entry = zin.getNextEntry()) != null){
entries.add(entry.getName());
}
}catch(IOException ex){
throw new RuntimeException(ex.getMessage(), ex);
}
return entries;
}
}
Java8 です。