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

Javaの標準APIでファイルを含むディレクトリのZip圧縮を試してみたが...

gigazine.net

Googleはこれまで「ページのランク付けにChromeのデータは利用していない」と説明してきましたが、実際は上述のようにChromeのデータを利用するモジュールが存在していたことから、キング氏は「『ウソをついた』というのは厳しい表現だが、この場合に使う唯一の正確な言葉だ」と、Googleに厳しい目を向けています。

Googleの検索アルゴリズムに関する内部文書が流出、Chromeのデータをページランク付けに利用するなどGoogleのウソが明らかに - GIGAZINE

SEO(Search Engine Optimization)とかモヤっとしてましたが、上記の情報が正しいとすると、Googleはこれまで偽証してきたことになってしまいますな...

Javaの標準APIでファイルを含むディレクトリのZip圧縮を試してみたが...

Java標準のAPIでZip圧縮・展開が実現できるらしいので、

qiita.com

⇧ 上記サイト様を参考にZip圧縮を試してみます。

参考サイト様のそのままを利用させていただきました。

■/test-zip/build.gradle

plugins {
	id 'java'
	id 'war'
	id 'org.springframework.boot' version '3.3.0'
	id 'io.spring.dependency-management' version '1.1.5'
}

group = 'com.example'
version = '0.0.1-SNAPSHOT'

java {
	sourceCompatibility = '17'
}

configurations {
	compileOnly {
		extendsFrom annotationProcessor
	}
}

repositories {
	mavenCentral()
}

dependencies {
	implementation 'org.springframework.boot:spring-boot-starter-web'
	compileOnly 'org.projectlombok:lombok'
	developmentOnly 'org.springframework.boot:spring-boot-devtools'
	annotationProcessor 'org.projectlombok:lombok'
	providedRuntime 'org.springframework.boot:spring-boot-starter-tomcat'
	testImplementation 'org.springframework.boot:spring-boot-starter-test'
	testRuntimeOnly 'org.junit.platform:junit-platform-launcher'

}

tasks.named('test') {
	useJUnitPlatform()
}

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

package com.example.demo.util;

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.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

public class ZipUtil {

	/**
	 * 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);
					}
				});
	}

}

動作確認用。

■/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.StandardOpenOption;

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

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

	@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圧縮処理
		ZipUtil.zip(zipName, zipInput, StandardOpenOption.CREATE, StandardCharsets.UTF_8);
		
	}
	
}

⇧ で、動作確認。

手動で展開(解凍)してみた感じ、Zip圧縮前の構成が維持できておりました。

再帰処理とか自前で実装しないといけなかったり、なかなか辛いですな...

展開(解凍)も面倒くさい感じになるんかな?

一応、

reasonable-code.com

Javaの標準ライブラリjava.util.zipを使って実現できるのですが、ストリーム処理の実装を行う必要があったり、またパスワード付きzipに対応していなかったりします。

その点、zip4jライブラリを使えば、たった1行でzipファイルの解凍・圧縮が行えます。

【たった1行】Javaでzipファイルの解凍・圧縮を行う方法 - Reasonable Code

⇧ 上記サイト様によりますと、Java標準のAPI以外のライブラリがあるようなので、試してみる。

■/test-zip/build.gradle

plugins {
	id 'java'
	id 'war'
	id 'org.springframework.boot' version '3.3.0'
	id 'io.spring.dependency-management' version '1.1.5'
}

group = 'com.example'
version = '0.0.1-SNAPSHOT'

java {
	sourceCompatibility = '17'
}

configurations {
	compileOnly {
		extendsFrom annotationProcessor
	}
}

repositories {
	mavenCentral()
}

dependencies {
	implementation 'org.springframework.boot:spring-boot-starter-web'
	compileOnly 'org.projectlombok:lombok'
	developmentOnly 'org.springframework.boot:spring-boot-devtools'
	annotationProcessor 'org.projectlombok:lombok'
	providedRuntime 'org.springframework.boot:spring-boot-starter-tomcat'
	testImplementation 'org.springframework.boot:spring-boot-starter-test'
	testRuntimeOnly 'org.junit.platform:junit-platform-launcher'

}

tasks.named('test') {
	useJUnitPlatform()
}

■/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.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.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

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

public class ZipUtil {

	/**
	 * 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);
					}
				});
	}

	/**
	 * ライブラリ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;

	@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圧縮処理
		ZipUtil.zip(zipName, zipInput, StandardOpenOption.CREATE, StandardCharsets.UTF_8);
		
	}
	
	@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);
	}
	
	@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);
	}
	
	@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);
	}
	
	@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));
	}
	
	@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);
	}
}

で、試してみました。

test03、test04を実行。

■test03、test04の実行結果

test04の展開(解凍)の結果を削除し、test05、test06を実行する。

■test05、test06の実行結果

⇧ ライブラリZip4jを使って良いなら使いたいところですな。

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

今回はこのへんで。