「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) {

案内メニュー