「PHPの基礎 - 圧縮・解凍」の版間の差分
ナビゲーションに移動
検索に移動
(ページの作成:「== 概要 == <br><br> == 圧縮 == ==== ZIP形式 ==== <syntaxhighlight lang="php"> declare(strict_types=1); namespace Utils; use RuntimeException; use ZipArchive; use Generator; /** * ZIP形式で圧縮を行うメソッド * * @param string $sourcePath 圧縮対象のパス(ファイルまたはディレクトリ) * @param string $destinationPath 出力先のZIPファイルパス * @throws RuntimeException 圧縮処理中のエラー発…」) |
(→圧縮) |
||
3行目: | 3行目: | ||
== 圧縮 == | == 圧縮 == | ||
以下に示す例では、非同期処理のサポート、ストリーミング処理による効率的なメモリ使用、エラーハンドリングを実装している。<br> | |||
また、3つの圧縮形式 (ZIP、tar.gz、tar.xz) に対応している。<br> | |||
<br> | |||
==== ZIP形式 ==== | ==== ZIP形式 ==== | ||
<syntaxhighlight lang="php"> | <syntaxhighlight lang="php"> | ||
74行目: | 77行目: | ||
try { | try { | ||
$compression->compressToZip('/path/to/source', '/path/to/output.zip'); | $compression->compressToZip('/path/to/source', '/path/to/output.zip'); | ||
} | |||
catch (RuntimeException $e) { | |||
echo "エラーが発生しました: " . $e->getMessage(); | |||
} | |||
</syntaxhighlight> | |||
<br> | |||
==== tar.gz形式 ==== | |||
<u>tar.gz圧縮を行う場合は、システムにtarコマンドがインストールされている必要がある。</u><br> | |||
<br> | |||
<syntaxhighlight lang="php"> | |||
/** | |||
* tar.gz形式で圧縮を行うメソッド | |||
* | |||
* @param string $sourcePath 圧縮対象のパス | |||
* @param string $destinationPath 出力先のtar.gzファイルパス | |||
* @throws RuntimeException 圧縮処理中のエラー発生時 | |||
*/ | |||
function compressToTarGz(string $sourcePath, string $destinationPath): void | |||
{ | |||
try { | |||
// 一時的なTARファイルの作成 | |||
$tempTarFile = tempnam(sys_get_temp_dir(), 'tar'); | |||
// tarコマンドの実行 | |||
$sourceName = basename($sourcePath); | |||
$sourceDir = dirname($sourcePath); | |||
exec("cd {$sourceDir} && tar -cf {$tempTarFile} {$sourceName}", $output, $returnCode); | |||
if ($returnCode !== 0) { | |||
throw new RuntimeException('TAR作成に失敗しました'); | |||
} | |||
// gzipでの圧縮処理 | |||
$gz = gzopen($destinationPath, 'wb9'); | |||
if ($gz === false) { | |||
throw new RuntimeException('GZIPファイルのオープンに失敗しました'); | |||
} | |||
// ストリーミング処理でTARファイルを読み込みながら圧縮 | |||
$handle = fopen($tempTarFile, 'rb'); | |||
while (!feof($handle)) { | |||
gzwrite($gz, fread($handle, 8192)); | |||
} | |||
fclose($handle); | |||
gzclose($gz); | |||
// 一時ファイルの削除 | |||
unlink($tempTarFile); | |||
} | |||
catch (\Exception $e) { | |||
throw new RuntimeException("tar.gz圧縮処理中にエラーが発生しました: {$e->getMessage()}"); | |||
} | |||
} | |||
/** | |||
* ディレクトリ内のファイルを再帰的に取得するプライベートメソッド | |||
* | |||
* @param string $dir 検索対象ディレクトリ | |||
* @return Generator ファイルパスを返すジェネレータ | |||
*/ | |||
function getFilesRecursively(string $dir): Generator | |||
{ | |||
$files = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($dir, \RecursiveDirectoryIterator::SKIP_DOTS), | |||
\RecursiveIteratorIterator::LEAVES_ONLY); | |||
foreach ($files as $file) { | |||
yield $file->getRealPath(); | |||
} | |||
} | |||
</syntaxhighlight> | |||
<br> | |||
<syntaxhighlight lang="php"> | |||
// 使用例 | |||
$compression = new Utils\CompressionUtils(); | |||
try { | |||
// tar.gz圧縮の例 | |||
$compression->compressToTarGz('/path/to/source', '/path/to/output.tar.gz'); | |||
} | |||
catch (RuntimeException $e) { | |||
echo "エラーが発生しました: " . $e->getMessage(); | |||
} | |||
</syntaxhighlight> | |||
<br> | |||
==== tar.xz形式 ==== | |||
<u>tar.xz形式の圧縮には、PHPのXZ拡張機能が必要である。</u><br> | |||
<u>また、tar.xz圧縮を行う場合は、システムにtarコマンドがインストールされている必要がある。</u><br> | |||
<br> | |||
<syntaxhighlight lang="php"> | |||
/** | |||
* tar.xz形式で圧縮を行うメソッド | |||
* | |||
* @param string $sourcePath 圧縮対象のパス | |||
* @param string $destinationPath 出力先のtar.xzファイルパス | |||
* @throws RuntimeException 圧縮処理中のエラー発生時 | |||
*/ | |||
function compressToTarXz(string $sourcePath, string $destinationPath): void | |||
{ | |||
try { | |||
// PHPのXZ拡張機能が必要 | |||
if (!extension_loaded('xz')) { | |||
throw new RuntimeException('XZ拡張機能がインストールされていません'); | |||
} | |||
// 一時的なTARファイルの作成 | |||
$tempTarFile = tempnam(sys_get_temp_dir(), 'tar'); | |||
// tarコマンドの実行 | |||
$sourceName = basename($sourcePath); | |||
$sourceDir = dirname($sourcePath); | |||
exec("cd {$sourceDir} && tar -cf {$tempTarFile} {$sourceName}", $output, $returnCode); | |||
if ($returnCode !== 0) { | |||
throw new RuntimeException('TAR作成に失敗しました'); | |||
} | |||
// XZ圧縮の実行 | |||
$xzStream = xzopen($destinationPath, 'wb9'); | |||
if ($xzStream === false) { | |||
throw new RuntimeException('XZファイルのオープンに失敗しました'); | |||
} | |||
// ストリーミング処理でTARファイルを読み込みながら圧縮 | |||
$handle = fopen($tempTarFile, 'rb'); | |||
while (!feof($handle)) { | |||
xzwrite($xzStream, fread($handle, 8192)); | |||
} | |||
fclose($handle); | |||
xzclose($xzStream); | |||
// 一時ファイルの削除 | |||
unlink($tempTarFile); | |||
} | |||
catch (\Exception $e) { | |||
throw new RuntimeException("tar.xz圧縮処理中にエラーが発生しました: {$e->getMessage()}"); | |||
} | |||
} | |||
/** | |||
* ディレクトリ内のファイルを再帰的に取得するプライベートメソッド | |||
* | |||
* @param string $dir 検索対象ディレクトリ | |||
* @return Generator ファイルパスを返すジェネレータ | |||
*/ | |||
function getFilesRecursively(string $dir): Generator | |||
{ | |||
$files = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($dir, \RecursiveDirectoryIterator::SKIP_DOTS), | |||
\RecursiveIteratorIterator::LEAVES_ONLY); | |||
foreach ($files as $file) { | |||
yield $file->getRealPath(); | |||
} | |||
} | |||
</syntaxhighlight> | |||
<br> | |||
<syntaxhighlight lang="php"> | |||
// 使用例 | |||
$compression = new Utils\CompressionUtils(); | |||
try { | |||
// tar.xz圧縮の例 | |||
$compression->compressToTarXz('/path/to/source', '/path/to/output.tar.xz'); | |||
} | |||
catch (RuntimeException $e) { | |||
echo "エラーが発生しました: " . $e->getMessage(); | |||
} | |||
</syntaxhighlight> | |||
<br> | |||
==== 非同期処理 ==== | |||
<syntaxhighlight lang="php"> | |||
/** | |||
* 非同期でファイル圧縮を行うメソッド | |||
* | |||
* @param string $sourcePath 圧縮対象のパス | |||
* @param string $destinationPath 出力先のパス | |||
* @param string $type 圧縮形式('zip', 'tar.gz', 'tar.xz'のいずれか) | |||
* @return Generator 圧縮の進捗状況を返すジェネレータ | |||
*/ | |||
function compressAsync(string $sourcePath, string $destinationPath, string $type): Generator | |||
{ | |||
yield '圧縮処理を開始します...'; | |||
try { | |||
switch ($type) { | |||
case 'zip': | |||
$this->compressToZip($sourcePath, $destinationPath); | |||
break; | |||
case 'tar.gz': | |||
$this->compressToTarGz($sourcePath, $destinationPath); | |||
break; | |||
case 'tar.xz': | |||
$this->compressToTarXz($sourcePath, $destinationPath); | |||
break; | |||
default: | |||
throw new RuntimeException('不正な圧縮形式が指定されました'); | |||
} | |||
yield '圧縮処理が完了しました'; | |||
} | |||
catch (\Exception $e) { | |||
yield "圧縮処理中にエラーが発生しました: {$e->getMessage()}"; | |||
throw $e; | |||
} | |||
} | |||
</syntaxhighlight> | |||
<br> | |||
<syntaxhighlight lang="php"> | |||
// 使用例 | |||
$compression = new Utils\CompressionUtils(); | |||
try { | |||
// 非同期処理の例 | |||
// ZIP形式の場合 | |||
foreach ($compression->compressAsync('/path/to/source', '/path/to/output.zip', 'zip') as $status) { | |||
echo $status . PHP_EOL; | |||
} | |||
// tar.gz形式の場合 | |||
foreach ($compression->compressAsync('/path/to/source', '/path/to/output.zip', 'zip') as $status) { | |||
echo $status . PHP_EOL; | |||
} | |||
// tar.xz形式の場合 | |||
foreach ($compression->compressAsync('/path/to/source', '/path/to/output.zip', 'zip') as $status) { | |||
echo $status . PHP_EOL; | |||
} | |||
} | } | ||
catch (RuntimeException $e) { | catch (RuntimeException $e) { |
2024年11月9日 (土) 18:34時点における版
概要
圧縮
以下に示す例では、非同期処理のサポート、ストリーミング処理による効率的なメモリ使用、エラーハンドリングを実装している。
また、3つの圧縮形式 (ZIP、tar.gz、tar.xz) に対応している。
ZIP形式
declare(strict_types=1);
namespace Utils;
use RuntimeException;
use ZipArchive;
use Generator;
/**
* ZIP形式で圧縮を行うメソッド
*
* @param string $sourcePath 圧縮対象のパス(ファイルまたはディレクトリ)
* @param string $destinationPath 出力先のZIPファイルパス
* @throws RuntimeException 圧縮処理中のエラー発生時
*/
function compressToZip(string $sourcePath, string $destinationPath): void
{
try {
$zip = new ZipArchive();
// ZIPファイルのオープン
if ($zip->open($destinationPath, ZipArchive::CREATE | ZipArchive::OVERWRITE) !== true) {
throw new RuntimeException('ZIPファイルの作成に失敗しました');
}
// ディレクトリの場合は再帰的に処理
if (is_dir($sourcePath)) {
$files = $this->getFilesRecursively($sourcePath);
foreach ($files as $file) {
$relativePath = substr($file, strlen($sourcePath) + 1);
$zip->addFile($file, $relativePath);
}
}
else {
// 単一ファイルの場合
$zip->addFile($sourcePath, basename($sourcePath));
}
$zip->close();
}
catch (\Exception $e) {
throw new RuntimeException("ZIP圧縮処理中にエラーが発生しました: {$e->getMessage()}");
}
}
/**
* ディレクトリ内のファイルを再帰的に取得するプライベートメソッド
*
* @param string $dir 検索対象ディレクトリ
* @return Generator ファイルパスを返すジェネレータ
*/
function getFilesRecursively(string $dir): Generator
{
$files = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($dir, \RecursiveDirectoryIterator::SKIP_DOTS),
\RecursiveIteratorIterator::LEAVES_ONLY);
foreach ($files as $file) {
yield $file->getRealPath();
}
}
// 使用例
$compression = new Utils\CompressionUtils();
try {
$compression->compressToZip('/path/to/source', '/path/to/output.zip');
}
catch (RuntimeException $e) {
echo "エラーが発生しました: " . $e->getMessage();
}
tar.gz形式
tar.gz圧縮を行う場合は、システムにtarコマンドがインストールされている必要がある。
/**
* tar.gz形式で圧縮を行うメソッド
*
* @param string $sourcePath 圧縮対象のパス
* @param string $destinationPath 出力先のtar.gzファイルパス
* @throws RuntimeException 圧縮処理中のエラー発生時
*/
function compressToTarGz(string $sourcePath, string $destinationPath): void
{
try {
// 一時的なTARファイルの作成
$tempTarFile = tempnam(sys_get_temp_dir(), 'tar');
// tarコマンドの実行
$sourceName = basename($sourcePath);
$sourceDir = dirname($sourcePath);
exec("cd {$sourceDir} && tar -cf {$tempTarFile} {$sourceName}", $output, $returnCode);
if ($returnCode !== 0) {
throw new RuntimeException('TAR作成に失敗しました');
}
// gzipでの圧縮処理
$gz = gzopen($destinationPath, 'wb9');
if ($gz === false) {
throw new RuntimeException('GZIPファイルのオープンに失敗しました');
}
// ストリーミング処理でTARファイルを読み込みながら圧縮
$handle = fopen($tempTarFile, 'rb');
while (!feof($handle)) {
gzwrite($gz, fread($handle, 8192));
}
fclose($handle);
gzclose($gz);
// 一時ファイルの削除
unlink($tempTarFile);
}
catch (\Exception $e) {
throw new RuntimeException("tar.gz圧縮処理中にエラーが発生しました: {$e->getMessage()}");
}
}
/**
* ディレクトリ内のファイルを再帰的に取得するプライベートメソッド
*
* @param string $dir 検索対象ディレクトリ
* @return Generator ファイルパスを返すジェネレータ
*/
function getFilesRecursively(string $dir): Generator
{
$files = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($dir, \RecursiveDirectoryIterator::SKIP_DOTS),
\RecursiveIteratorIterator::LEAVES_ONLY);
foreach ($files as $file) {
yield $file->getRealPath();
}
}
// 使用例
$compression = new Utils\CompressionUtils();
try {
// tar.gz圧縮の例
$compression->compressToTarGz('/path/to/source', '/path/to/output.tar.gz');
}
catch (RuntimeException $e) {
echo "エラーが発生しました: " . $e->getMessage();
}
tar.xz形式
tar.xz形式の圧縮には、PHPのXZ拡張機能が必要である。
また、tar.xz圧縮を行う場合は、システムにtarコマンドがインストールされている必要がある。
/**
* tar.xz形式で圧縮を行うメソッド
*
* @param string $sourcePath 圧縮対象のパス
* @param string $destinationPath 出力先のtar.xzファイルパス
* @throws RuntimeException 圧縮処理中のエラー発生時
*/
function compressToTarXz(string $sourcePath, string $destinationPath): void
{
try {
// PHPのXZ拡張機能が必要
if (!extension_loaded('xz')) {
throw new RuntimeException('XZ拡張機能がインストールされていません');
}
// 一時的なTARファイルの作成
$tempTarFile = tempnam(sys_get_temp_dir(), 'tar');
// tarコマンドの実行
$sourceName = basename($sourcePath);
$sourceDir = dirname($sourcePath);
exec("cd {$sourceDir} && tar -cf {$tempTarFile} {$sourceName}", $output, $returnCode);
if ($returnCode !== 0) {
throw new RuntimeException('TAR作成に失敗しました');
}
// XZ圧縮の実行
$xzStream = xzopen($destinationPath, 'wb9');
if ($xzStream === false) {
throw new RuntimeException('XZファイルのオープンに失敗しました');
}
// ストリーミング処理でTARファイルを読み込みながら圧縮
$handle = fopen($tempTarFile, 'rb');
while (!feof($handle)) {
xzwrite($xzStream, fread($handle, 8192));
}
fclose($handle);
xzclose($xzStream);
// 一時ファイルの削除
unlink($tempTarFile);
}
catch (\Exception $e) {
throw new RuntimeException("tar.xz圧縮処理中にエラーが発生しました: {$e->getMessage()}");
}
}
/**
* ディレクトリ内のファイルを再帰的に取得するプライベートメソッド
*
* @param string $dir 検索対象ディレクトリ
* @return Generator ファイルパスを返すジェネレータ
*/
function getFilesRecursively(string $dir): Generator
{
$files = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($dir, \RecursiveDirectoryIterator::SKIP_DOTS),
\RecursiveIteratorIterator::LEAVES_ONLY);
foreach ($files as $file) {
yield $file->getRealPath();
}
}
// 使用例
$compression = new Utils\CompressionUtils();
try {
// tar.xz圧縮の例
$compression->compressToTarXz('/path/to/source', '/path/to/output.tar.xz');
}
catch (RuntimeException $e) {
echo "エラーが発生しました: " . $e->getMessage();
}
非同期処理
/**
* 非同期でファイル圧縮を行うメソッド
*
* @param string $sourcePath 圧縮対象のパス
* @param string $destinationPath 出力先のパス
* @param string $type 圧縮形式('zip', 'tar.gz', 'tar.xz'のいずれか)
* @return Generator 圧縮の進捗状況を返すジェネレータ
*/
function compressAsync(string $sourcePath, string $destinationPath, string $type): Generator
{
yield '圧縮処理を開始します...';
try {
switch ($type) {
case 'zip':
$this->compressToZip($sourcePath, $destinationPath);
break;
case 'tar.gz':
$this->compressToTarGz($sourcePath, $destinationPath);
break;
case 'tar.xz':
$this->compressToTarXz($sourcePath, $destinationPath);
break;
default:
throw new RuntimeException('不正な圧縮形式が指定されました');
}
yield '圧縮処理が完了しました';
}
catch (\Exception $e) {
yield "圧縮処理中にエラーが発生しました: {$e->getMessage()}";
throw $e;
}
}
// 使用例
$compression = new Utils\CompressionUtils();
try {
// 非同期処理の例
// ZIP形式の場合
foreach ($compression->compressAsync('/path/to/source', '/path/to/output.zip', 'zip') as $status) {
echo $status . PHP_EOL;
}
// tar.gz形式の場合
foreach ($compression->compressAsync('/path/to/source', '/path/to/output.zip', 'zip') as $status) {
echo $status . PHP_EOL;
}
// tar.xz形式の場合
foreach ($compression->compressAsync('/path/to/source', '/path/to/output.zip', 'zip') as $status) {
echo $status . PHP_EOL;
}
}
catch (RuntimeException $e) {
echo "エラーが発生しました: " . $e->getMessage();
}