※当サイトの記事には、広告・プロモーションが含まれます。

Javaの標準APIでZipの展開(解凍)を展開先を指定して行う

gigazine.net

SEO八百長だった可能性があると...

Googleさん、大チョンボですな...

Javaの標準APIでZipの展開(解凍)を展開先を指定して行う

前回、

ts0818.hatenablog.com

Javaの標準APIでZip圧縮を試してみましたが(ライブラリZip4jというものも試してます)、Javaの標準APIによるZipの展開(解凍)を試していなかったので試してみようと。

ネットの情報を漁ったところ、先人が情報発信してくれておりました、ありがたや。

dk521123.hatenablog.com

www.saka-en.com

⇧ 上記サイト様が情報を公開してくださっているので、利用させていただきました。

前回のソースコードを修正。

Javaの標準APIとライブラリZip4jがバッティングしてしまうので、クラスを分けました。

■/test-zip/src/main/java/com/example/demo/util/ZipStandardUtil.java

package com.example.demo.util;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.nio.file.OpenOption;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Enumeration;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import java.util.zip.ZipInputStream;
import java.util.zip.ZipOutputStream;

/**
 * Java標準のAPIのみでZip処理
 */
public class ZipStandardUtil {

	/**
	 * Zip圧縮
	 * @param zipName Zipファイル名
	 * @param targetRootPath Zip対象のルートパス
	 * @param option 
	 * @param encoding 文字コード
	 * @return
	 */
	public static boolean zip(String zipName, String targetRootPath, OpenOption option, Charset encoding) {
		Path pathZipInput = Paths.get(targetRootPath);
		Path pathZipOutput = Paths.get(zipName);
		//int countZip = 0;

		try (OutputStream os = Files.newOutputStream(pathZipOutput, option);
				ZipOutputStream zos = new ZipOutputStream(os, encoding)) {

			//for (String targetPathStr: targetPathList) {

			if (Files.isDirectory(pathZipInput)) {
				directoryZip(pathZipInput.getNameCount(), pathZipInput, zos);

			} else {
				// 新しいファイル名を指定し、zip中に設定
				ZipEntry zipEntry = new ZipEntry(pathZipInput.getFileName().toString());
				zos.putNextEntry(zipEntry);
				byte[] bytes = Files.readAllBytes(pathZipInput);
				zos.write(bytes);
			}
			zos.closeEntry();

			//}
		} catch (IOException e) {
			// TODO 自動生成された catch ブロック
			e.printStackTrace();
		}

		return true;
	}

	private static void directoryZip(int rootCount, Path path, ZipOutputStream zip) throws IOException {
		Files.list(path).forEach(
				p -> {
					try {
						var pathName = p.subpath(rootCount, p.getNameCount());
						if (Files.isDirectory(p)) {
							zip.putNextEntry(new ZipEntry(pathName + "/"));
							directoryZip(rootCount, p, zip);
						} else {
							zip.putNextEntry(new ZipEntry(pathName.toString()));
							zip.write(Files.readAllBytes(p));
						}
					} catch (IOException e) {
						throw new RuntimeException("ファイル操作で問題が発生しました。", e);
					}
				});
	}

	/**
	 * Zip展開(解凍)
	 * @param zipFilePath
	 */
	public static void unzip(Path zipFilePath, String decompressDir) {

		try {
			File zipFile = new File(zipFilePath.toString());

			ZipInputStream zis = new ZipInputStream(new FileInputStream(zipFile));
			ZipEntry entry = null;
			while ((entry = zis.getNextEntry()) != null) {
				if (entry.isDirectory()) {
					new File(entry.getName()).mkdirs();
				} else {
					File parent = new File(entry.getName()).getParentFile();
					if (parent != null) {
						parent.mkdirs();
					}
					FileOutputStream out = new FileOutputStream(entry.getName());
					byte[] buf = new byte[1024];
					int size = 0;
					while ((size = zis.read(buf)) != -1) {
						out.write(buf, 0, size);
					}
					out.close();
				}
				zis.closeEntry();
			}
			zis.close();
		} catch (FileNotFoundException e) {
			// TODO 自動生成された catch ブロック
			e.printStackTrace();
		} catch (IOException e) {
			// TODO 自動生成された catch ブロック
			e.printStackTrace();
		}
	}

	public static boolean unzip(String zipFileFullPath, String unzipPath) {

		File baseFile = new File(zipFileFullPath);
		File baseDir = new File(baseFile.getParent(),
				baseFile.getName().substring(0, baseFile.getName().lastIndexOf(".")));
		if (!baseDir.mkdir())
			System.out.println("Couldn't create directory because directory with the same name exists.: " + baseDir);

		ZipFile zipFile = null;
		try {
			// ZIPファイルオブジェクト作成
			zipFile = new ZipFile(zipFileFullPath);

			// ZIPファイル内のファイルを列挙
			Enumeration<? extends ZipEntry> enumZip = zipFile.entries();

			// ZIPファイル内の全てのファイルを展開
			while (enumZip.hasMoreElements()) {

				// ZIP内のエントリを取得
				ZipEntry zipEntry = (java.util.zip.ZipEntry) enumZip.nextElement();

				//出力ファイル取得
				File unzipFile = new File(unzipPath);
				File outFile = new File(unzipFile.getAbsolutePath() + "/" + baseDir.getName(), zipEntry.getName());

				if (zipEntry.isDirectory())
					outFile.mkdir();
				else {
					// 圧縮ファイル入力ストリーム作成
					BufferedInputStream in = new BufferedInputStream(zipFile.getInputStream(zipEntry));

					// 親ディレクトリがない場合、ディレクトリ作成
					if (!outFile.getParentFile().exists())
						outFile.getParentFile().mkdirs();

					// 出力オブジェクト取得
					BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(outFile));

					// 読み込みバッファ作成
					byte[] buffer = new byte[1024];

					// 解凍ファイル出力
					int readSize = 0;
					while ((readSize = in.read(buffer)) != -1) {
						out.write(buffer, 0, readSize);
					}
					// クローズ
					try {
						out.close();
					} catch (Exception e) {
					}
					try {
						in.close();
					} catch (Exception e) {
					}
				}
			}
			// 解凍処理成功
			return true;
		} catch (Exception e) {
			// エラーログ出力
			System.out.println(e.toString());
			// 解凍処理失敗
			return false;
		} finally {
			if (zipFile != null)
				try {
					zipFile.close();
				} catch (Exception e) {
				}
		}
	}

}
    

■/test-zip/src/main/java/com/example/demo/util/ZipUtil.java

package com.example.demo.util;

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;

import net.lingala.zip4j.ZipFile;
import net.lingala.zip4j.exception.ZipException;

/**
 * ライブラリZip4jを利用したZip処理
 */
public class ZipUtil {
	
	/**
	 * ライブラリZip4jで圧縮
	 * @param zipFilePath Zip圧縮後のファイルパス
	 * @param compressDir Zip圧縮対象の起点ディレクトリ
	 */
	public static void zip(String zipFilePath, String compressDir ) {
		try {
			ZipFile zipFile = new ZipFile(zipFilePath);
			zipFile.addFolder(new File(compressDir));
			zipFile.close();
			
		} catch (ZipException e) {
			// TODO 自動生成された catch ブロック
			e.printStackTrace();
		} catch (IOException e) {
			// TODO 自動生成された catch ブロック
			e.printStackTrace();
		}
	}
	
	/**
	 * ライブラリZip4jで圧縮
	 * @param zipFilePath
	 * @param targetPath
	 */
	public static void zip(String zipFilePath, Path targetPath) {
		try {
			ZipFile zipFile = new ZipFile(zipFilePath);
			
			Files.list(targetPath).forEach(path -> {
				try {
					zipFile.addFolder(path.toFile());
				} catch (ZipException e) {
					// TODO 自動生成された catch ブロック
					e.printStackTrace();
				}
			});
			zipFile.close();
		} catch (IOException e) {
			// TODO 自動生成された catch ブロック
			e.printStackTrace();
		}
	}
	
	/**
	 * ライブラリZip4jで展開(解凍)
	 * @param zipFilePath Zip圧縮後のファイルパス
	 * @param decompressDir 展開(解凍)先のディレクトリパス
	 */
	public static void unzip(String zipFilePath, String decompressDir ) {
		try  {
			ZipFile zipFile = new ZipFile(zipFilePath);
			zipFile.extractAll(decompressDir);
			zipFile.close();
			
		} catch (ZipException e) {
			// TODO 自動生成された catch ブロック
			e.printStackTrace();
		} catch (IOException e) {
			// TODO 自動生成された catch ブロック
			e.printStackTrace();
		}
	}
	

}
    

■/test-zip/src/test/java/com/example/demo/util/TestZipUtil.java

package com.example.demo.util;

import java.nio.charset.StandardCharsets;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;

import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;

@SpringBootTest
public class TestZipUtil {
	
//	@Autowired
//	private ZipUtil zipUtil;

	/**
	 * Javaの標準APIのZip処理
* Zip圧縮の確認 */ @Test public void test01() { // Zip圧縮対象の起点のディレクトリ String zipInput= "C:\\Eclipse-2023-06\\workspace\\test-zip\\target"; // Zip圧縮後のファイル名 String zipName = "C:\\Eclipse-2023-06\\workspace\\test-zip\\output\\office.zip"; // Zip圧縮処理 ZipStandardUtil.zip(zipName, zipInput, StandardOpenOption.CREATE, StandardCharsets.UTF_8); } /** * ライブラリZip4jを利用したZip処理
* Zip展開(解凍)の確認 */ @Test public void test02 () { // Zip圧縮後のファイル名 String zipName = "C:\\Eclipse-2023-06\\workspace\\test-zip\\output\\office.zip"; // Zip圧縮対象の起点のディレクトリ String zipDecompressDir= "C:\\Eclipse-2023-06\\workspace\\test-zip\\output"; ZipUtil.unzip(zipName, zipDecompressDir); } /** * ライブラリZip4jを利用したZip処理
* Zip圧縮の確認 */ @Test public void test03 () { // Zip圧縮対象の起点のディレクトリ String zipInput= "C:\\Eclipse-2023-06\\workspace\\test-zip\\target"; // Zip圧縮後のファイル名 String zipName = "C:\\Eclipse-2023-06\\workspace\\test-zip\\output\\zip4j-office.zip"; ZipUtil.zip(zipName, zipInput); } /** * ライブラリZip4jを利用したZip処理
* Zip展開(解凍)の確認 */ @Test public void test04 () { // Zip圧縮後のファイル名 String zipName = "C:\\Eclipse-2023-06\\workspace\\test-zip\\output\\zip4j-office.zip"; // Zip圧縮対象の起点のディレクトリ String zipDecompressDir= "C:\\Eclipse-2023-06\\workspace\\test-zip\\output"; ZipUtil.unzip(zipName, zipDecompressDir); } /** * ライブラリZip4jを利用したZip処理
* Zip圧縮の確認 */ @Test public void test05 () { // Zip圧縮対象の起点のディレクトリ String zipInput= "C:\\Eclipse-2023-06\\workspace\\test-zip\\target"; // Zip圧縮後のファイル名 String zipName = "C:\\Eclipse-2023-06\\workspace\\test-zip\\output\\test05_zip4j-office.zip"; ZipUtil.zip(zipName, Paths.get(zipInput)); } /** * ライブラリZip4jを利用したZip処理
* Zip展開(解凍)の確認 */ @Test public void test06 () { // Zip圧縮後のファイル名 String zipName = "C:\\Eclipse-2023-06\\workspace\\test-zip\\output\\test05_zip4j-office.zip"; // Zip圧縮対象の起点のディレクトリ String zipDecompressDir= "C:\\Eclipse-2023-06\\workspace\\test-zip\\output"; ZipUtil.unzip(zipName, zipDecompressDir); } /** * Javaの標準APIのZip処理
* Zip展開(解凍)の確認 */ @Test public void test07 () { // Zip圧縮後のファイル名 String zipName = "C:\\Eclipse-2023-06\\workspace\\test-zip\\output\\test05_zip4j-office.zip"; // Zip展開(解凍)先 String unzipDir = "C:\\Eclipse-2023-06\\workspace\\test-zip\\output"; ZipUtil.unzip(zipName, unzipDir); } }

⇧ で、test07を実行すると、

指定した展開先に展開(解凍)されました。

ライブラリZip4jで、展開先(解凍)の指定ができたりするのであれば、ライブラリの力に頼りたいのだが...

毎度モヤモヤ感が半端ない…

今回はこのへんで。