📢 Webサイト閉鎖と移転のお知らせ
このWebサイトは2026年9月に閉鎖いたします。
新しい記事は移転先で追加しております。(旧サイトでは記事を追加しておりません)
| (同じ利用者による、間の4版が非表示) | |||
| 1行目: | 1行目: | ||
== 概要 == | == 概要 == | ||
PHPには、主に、Zlibライブラリを利用した圧縮機能が組み込まれている。<br> | |||
最も一般的なものは、gzcompress関数、gzuncompress関数があり、ZLIBフォーマットでデータを圧縮・解凍できる。<br> | |||
<br> | |||
基本的な使用例を以下に示す。<br> | |||
<syntaxhighlight lang="php"> | |||
$data = "圧縮したいテキストデータ"; | |||
$compressed = gzcompress($data); | |||
$original = gzuncompress($compressed); | |||
</syntaxhighlight> | |||
<br> | |||
代替的な圧縮方式であるGZIPフォーマットを使用する場合は、gzencode関数およびgzdecode関数が使用できる。<br> | |||
これらは、HTTPでの転送に適している。<br> | |||
<syntaxhighlight lang="php"> | |||
$compressed = gzencode($data); | |||
$original = gzdecode($compressed); | |||
</syntaxhighlight> | |||
<br> | |||
大きなファイルを扱う場合、PHPは圧縮ストリームをサポートしている。<br> | |||
<syntaxhighlight lang="php"> | |||
// 圧縮ファイルの書き込み | |||
$gz = gzopen('file.gz', 'w9'); | |||
gzwrite($gz, $data); | |||
gzclose($gz); | |||
// 圧縮ファイルの読み込み | |||
$gz = gzopen('file.gz', 'r'); | |||
$content = gzread($gz, 4096); | |||
gzclose($gz); | |||
</syntaxhighlight> | |||
<br> | |||
複数のファイルを扱う場合は、ZIPアーカイブが便利である。<br> | |||
PHPのZIPアーカイブ操作では、ZipArchiveクラスを使用する。<br> | |||
<syntaxhighlight lang="php"> | |||
$zip = new ZipArchive(); | |||
if ($zip->open('archive.zip', ZipArchive::CREATE) === TRUE) { | |||
$zip->addFromString('test.txt', 'ファイルの内容'); | |||
$zip->addFile('existing.txt', 'new_name.txt'); | |||
$zip->close(); | |||
} | |||
</syntaxhighlight> | |||
<br> | |||
圧縮レベルは、0 (無圧縮) から9 (最大圧縮) まで指定可能である。<br> | |||
ただし、高い圧縮レベルはCPU負荷が高くなるため、状況に応じて適切なレベルを選択することが重要である。<br> | |||
<br> | |||
また、バイナリデータを扱う場合は、データの破損を防ぐため、base64エンコードとの組み合わせを推奨する。<br> | |||
<syntaxhighlight lang="php"> | |||
$compressed = base64_encode(gzcompress($data)); | |||
$original = gzuncompress(base64_decode($compressed)); | |||
</syntaxhighlight> | |||
<br> | |||
これらの機能を組み合わせることにより、効率的なデータ圧縮と転送が実現できる。<br> | |||
特に大容量データの取り扱いやバックアップ処理等で重宝する。<br> | |||
<br><br> | <br><br> | ||
| 5行目: | 57行目: | ||
以下に示す例では、非同期処理のサポート、ストリーミング処理による効率的なメモリ使用、エラーハンドリングを実装している。<br> | 以下に示す例では、非同期処理のサポート、ストリーミング処理による効率的なメモリ使用、エラーハンドリングを実装している。<br> | ||
また、3つの圧縮形式 (ZIP、tar.gz、tar.xz) に対応している。<br> | また、3つの圧縮形式 (ZIP、tar.gz、tar.xz) に対応している。<br> | ||
<br> | |||
* declare(strict_types=1); | |||
*: これは、型の厳密なチェックを行うための宣言である。 | |||
*: 例えば、string型を期待する引数に整数を渡した場合にエラーとなる。 | |||
*: コードの信頼性を高めるために推奨されるが、必須ではない。 | |||
*: チーム開発で型の一貫性を保つ場合、バグの早期発見を重視する場合、型の安全性を重視する場合は記述する。 | |||
<br> | |||
* namespaceを使用する場合 | |||
*: これは、名前空間を定義するための宣言である。 | |||
*: コードの整理や名前の衝突を避けるために使用する。 | |||
*: 大規模なプロジェクトやライブラリとして使用する場合に有効であるが、単独のスクリプトとして使用する場合は不要である。 | |||
*: また、コードを再利用可能なライブラリとして提供する場合、オートローディングを使用する場合、他のライブラリとの名前衝突を避けたい場合等に記述する。 | |||
<br> | <br> | ||
==== ZIP形式 ==== | ==== ZIP形式 ==== | ||
| 318行目: | 382行目: | ||
// tar.xz形式の場合 | // tar.xz形式の場合 | ||
foreach ($compression->compressAsync('/path/to/source', '/path/to/output.zip', 'zip') as $status) { | foreach ($compression->compressAsync('/path/to/source', '/path/to/output.zip', 'zip') as $status) { | ||
echo $status . PHP_EOL; | |||
} | |||
} | |||
catch (RuntimeException $e) { | |||
echo "エラーが発生しました: " . $e->getMessage(); | |||
} | |||
</syntaxhighlight> | |||
<br><br> | |||
== 解凍 == | |||
以下に示す例では、非同期処理のサポート、ストリーミング処理による効率的なメモリ使用、エラーハンドリングを実装している。<br> | |||
また、3つの解凍形式 (ZIP、tar.gz、tar.xz) に対応している。<br> | |||
<br> | |||
* declare(strict_types=1); | |||
*: これは、型の厳密なチェックを行うための宣言である。 | |||
*: 例えば、string型を期待する引数に整数を渡した場合にエラーとなる。 | |||
*: コードの信頼性を高めるために推奨されるが、必須ではない。 | |||
*: チーム開発で型の一貫性を保つ場合、バグの早期発見を重視する場合、型の安全性を重視する場合は記述する。 | |||
<br> | |||
* namespaceを使用する場合 | |||
*: これは、名前空間を定義するための宣言である。 | |||
*: コードの整理や名前の衝突を避けるために使用する。 | |||
*: 大規模なプロジェクトやライブラリとして使用する場合に有効であるが、単独のスクリプトとして使用する場合は不要である。 | |||
*: また、コードを再利用可能なライブラリとして提供する場合、オートローディングを使用する場合、他のライブラリとの名前衝突を避けたい場合等に記述する。 | |||
<br> | |||
==== ZIP形式 ==== | |||
<syntaxhighlight lang="php"> | |||
declare(strict_types=1); | |||
namespace Utils; | |||
use RuntimeException; | |||
use ZipArchive; | |||
use Generator; | |||
/** | |||
* ZIPファイルを解凍するメソッド | |||
* | |||
* @param string $sourceFile 解凍対象のZIPファイルパス | |||
* @param string $destinationPath 解凍先のディレクトリパス | |||
* @throws RuntimeException 解凍処理中のエラー発生時 | |||
*/ | |||
function extractZip(string $sourceFile, string $destinationPath): void | |||
{ | |||
try { | |||
// ファイルの検証 | |||
validateFile($sourceFile); | |||
if (!file_exists($sourceFile)) { | |||
throw new RuntimeException('指定されたZIPファイルが存在しません'); | |||
} | |||
$zip = new ZipArchive(); | |||
$result = $zip->open($sourceFile); | |||
if ($result !== true) { | |||
throw new RuntimeException("ZIPファイルのオープンに失敗しました(エラーコード: {$result})"); | |||
} | |||
// 解凍先ディレクトリが存在しない場合は作成 | |||
if (!file_exists($destinationPath)) { | |||
if (!mkdir($destinationPath, 0777, true)) { | |||
throw new RuntimeException('解凍先ディレクトリの作成に失敗しました'); | |||
} | |||
} | |||
if (!$zip->extractTo($destinationPath)) { | |||
throw new RuntimeException('ZIPファイルの解凍に失敗しました'); | |||
} | |||
$zip->close(); | |||
} | |||
catch (\Exception $e) { | |||
throw new RuntimeException("ZIP解凍処理中にエラーが発生しました: {$e->getMessage()}"); | |||
} | |||
} | |||
/** | |||
* ファイルの存在確認と権限チェックを行うプライベートメソッド | |||
* | |||
* @param string $filePath チェック対象のファイルパス | |||
* @throws RuntimeException チェック失敗時 | |||
*/ | |||
function validateFile(string $filePath): void | |||
{ | |||
if (!file_exists($filePath)) { | |||
throw new RuntimeException("ファイルが存在しません: {$filePath}"); | |||
} | |||
if (!is_readable($filePath)) { | |||
throw new RuntimeException("ファイルの読み取り権限がありません: {$filePath}"); | |||
} | |||
if (!is_file($filePath)) { | |||
throw new RuntimeException("指定されたパスがファイルではありません: {$filePath}"); | |||
} | |||
} | |||
</syntaxhighlight> | |||
<br> | |||
<syntaxhighlight lang="php"> | |||
// 使用例 | |||
$decompression = new Utils\DecompressionUtils(); | |||
try { | |||
// ZIP解凍の例 | |||
$decompression->extractZip('/path/to/archive.zip', '/path/to/destination'); | |||
} | |||
catch (RuntimeException $e) { | |||
echo "エラーが発生しました: " . $e->getMessage(); | |||
} | |||
</syntaxhighlight> | |||
<br> | |||
==== tar.gz形式 ==== | |||
<u>tar.gz圧縮を行う場合は、システムにtarコマンドがインストールされている必要がある。</u><br> | |||
<br> | |||
<syntaxhighlight lang="php"> | |||
declare(strict_types=1); | |||
namespace Utils; | |||
use RuntimeException; | |||
use Generator; | |||
/** | |||
* tar.gzファイルを解凍するメソッド | |||
* | |||
* @param string $sourceFile 解凍対象のtar.gzファイルパス | |||
* @param string $destinationPath 解凍先のディレクトリパス | |||
* @throws RuntimeException 解凍処理中のエラー発生時 | |||
*/ | |||
function extractTarGz(string $sourceFile, string $destinationPath): void | |||
{ | |||
try { | |||
// ファイルの検証 | |||
validateFile($sourceFile); | |||
if (!file_exists($sourceFile)) { | |||
throw new RuntimeException('指定されたtar.gzファイルが存在しません'); | |||
} | |||
// 解凍先ディレクトリの作成 | |||
if (!file_exists($destinationPath)) { | |||
if (!mkdir($destinationPath, 0777, true)) { | |||
throw new RuntimeException('解凍先ディレクトリの作成に失敗しました'); | |||
} | |||
} | |||
// 一時的なTARファイルの作成 | |||
$tempTarFile = tempnam(sys_get_temp_dir(), 'tar'); | |||
// gzipファイルの解凍(ストリーミング処理) | |||
$gz = gzopen($sourceFile, 'rb'); | |||
if ($gz === false) { | |||
throw new RuntimeException('GZIPファイルのオープンに失敗しました'); | |||
} | |||
$tarHandle = fopen($tempTarFile, 'wb'); | |||
if ($tarHandle === false) { | |||
throw new RuntimeException('一時ファイルの作成に失敗しました'); | |||
} | |||
while (!gzeof($gz)) { | |||
fwrite($tarHandle, gzread($gz, 8192)); | |||
} | |||
gzclose($gz); | |||
fclose($tarHandle); | |||
// tarの展開 | |||
$currentDir = getcwd(); | |||
chdir($destinationPath); | |||
exec("tar -xf {$tempTarFile}", $output, $returnCode); | |||
chdir($currentDir); | |||
if ($returnCode !== 0) { | |||
throw new RuntimeException('TARファイルの展開に失敗しました'); | |||
} | |||
// 一時ファイルの削除 | |||
unlink($tempTarFile); | |||
} | |||
catch (\Exception $e) { | |||
throw new RuntimeException("tar.gz解凍処理中にエラーが発生しました: {$e->getMessage()}"); | |||
} | |||
} | |||
/** | |||
* ファイルの存在確認と権限チェックを行うプライベートメソッド | |||
* | |||
* @param string $filePath チェック対象のファイルパス | |||
* @throws RuntimeException チェック失敗時 | |||
*/ | |||
function validateFile(string $filePath): void | |||
{ | |||
if (!file_exists($filePath)) { | |||
throw new RuntimeException("ファイルが存在しません: {$filePath}"); | |||
} | |||
if (!is_readable($filePath)) { | |||
throw new RuntimeException("ファイルの読み取り権限がありません: {$filePath}"); | |||
} | |||
if (!is_file($filePath)) { | |||
throw new RuntimeException("指定されたパスがファイルではありません: {$filePath}"); | |||
} | |||
} | |||
</syntaxhighlight> | |||
<br> | |||
<syntaxhighlight lang="php"> | |||
// 使用例 | |||
$decompression = new Utils\DecompressionUtils(); | |||
try { | |||
// tar.gz解凍の例 | |||
$decompression->extractTarGz('/path/to/archive.tar.gz', '/path/to/destination'); | |||
} | |||
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"> | |||
declare(strict_types=1); | |||
namespace Utils; | |||
use RuntimeException; | |||
use Generator; | |||
/** | |||
* tar.xzファイルを解凍するメソッド | |||
* | |||
* @param string $sourceFile 解凍対象のtar.xzファイルパス | |||
* @param string $destinationPath 解凍先のディレクトリパス | |||
* @throws RuntimeException 解凍処理中のエラー発生時 | |||
*/ | |||
function extractTarXz(string $sourceFile, string $destinationPath): void | |||
{ | |||
try { | |||
// ファイルの検証 | |||
validateFile($sourceFile); | |||
if (!extension_loaded('xz')) { | |||
throw new RuntimeException('XZ拡張機能がインストールされていません'); | |||
} | |||
if (!file_exists($sourceFile)) { | |||
throw new RuntimeException('指定されたtar.xzファイルが存在しません'); | |||
} | |||
// 解凍先ディレクトリの作成 | |||
if (!file_exists($destinationPath)) { | |||
if (!mkdir($destinationPath, 0777, true)) { | |||
throw new RuntimeException('解凍先ディレクトリの作成に失敗しました'); | |||
} | |||
} | |||
// 一時的なTARファイルの作成 | |||
$tempTarFile = tempnam(sys_get_temp_dir(), 'tar'); | |||
// xzファイルの解凍(ストリーミング処理) | |||
$xz = xzopen($sourceFile, 'rb'); | |||
if ($xz === false) { | |||
throw new RuntimeException('XZファイルのオープンに失敗しました'); | |||
} | |||
$tarHandle = fopen($tempTarFile, 'wb'); | |||
if ($tarHandle === false) { | |||
throw new RuntimeException('一時ファイルの作成に失敗しました'); | |||
} | |||
while (!xzeof($xz)) { | |||
fwrite($tarHandle, xzread($xz, 8192)); | |||
} | |||
xzclose($xz); | |||
fclose($tarHandle); | |||
// tarの展開 | |||
$currentDir = getcwd(); | |||
chdir($destinationPath); | |||
exec("tar -xf {$tempTarFile}", $output, $returnCode); | |||
chdir($currentDir); | |||
if ($returnCode !== 0) { | |||
throw new RuntimeException('TARファイルの展開に失敗しました'); | |||
} | |||
// 一時ファイルの削除 | |||
unlink($tempTarFile); | |||
} | |||
catch (\Exception $e) { | |||
throw new RuntimeException("tar.xz解凍処理中にエラーが発生しました: {$e->getMessage()}"); | |||
} | |||
} | |||
/** | |||
* ファイルの存在確認と権限チェックを行うプライベートメソッド | |||
* | |||
* @param string $filePath チェック対象のファイルパス | |||
* @throws RuntimeException チェック失敗時 | |||
*/ | |||
function validateFile(string $filePath): void | |||
{ | |||
if (!file_exists($filePath)) { | |||
throw new RuntimeException("ファイルが存在しません: {$filePath}"); | |||
} | |||
if (!is_readable($filePath)) { | |||
throw new RuntimeException("ファイルの読み取り権限がありません: {$filePath}"); | |||
} | |||
if (!is_file($filePath)) { | |||
throw new RuntimeException("指定されたパスがファイルではありません: {$filePath}"); | |||
} | |||
} | |||
</syntaxhighlight> | |||
<br> | |||
<syntaxhighlight lang="php"> | |||
// 使用例 | |||
$decompression = new Utils\DecompressionUtils(); | |||
try { | |||
// tar.gz解凍の例 | |||
$decompression->extractTarXz('/path/to/archive.tar.xz', '/path/to/destination'); | |||
} | |||
catch (RuntimeException $e) { | |||
echo "エラーが発生しました: " . $e->getMessage(); | |||
} | |||
</syntaxhighlight> | |||
<br> | |||
==== 非同期処理 ==== | |||
<syntaxhighlight lang="php"> | |||
/** | |||
* 非同期でファイル解凍を行うメソッド | |||
* | |||
* @param string $sourceFile 解凍対象のファイルパス | |||
* @param string $destinationPath 解凍先のディレクトリパス | |||
* @param string $type 解凍形式('zip', 'tar.gz', 'tar.xz'のいずれか) | |||
* @return Generator 解凍の進捗状況を返すジェネレータ | |||
*/ | |||
function extractAsync(string $sourceFile, string $destinationPath, string $type): Generator | |||
{ | |||
yield '解凍処理を開始します...'; | |||
try { | |||
// ファイルの検証 | |||
validateFile($sourceFile); | |||
switch ($type) { | |||
case 'zip': | |||
yield 'ZIPファイルの解凍を開始します...'; | |||
$this->extractZip($sourceFile, $destinationPath); | |||
break; | |||
case 'tar.gz': | |||
yield 'tar.gzファイルの解凍を開始します...'; | |||
$this->extractTarGz($sourceFile, $destinationPath); | |||
break; | |||
case 'tar.xz': | |||
yield 'tar.xzファイルの解凍を開始します...'; | |||
$this->extractTarXz($sourceFile, $destinationPath); | |||
break; | |||
default: | |||
throw new RuntimeException('不正な解凍形式が指定されました'); | |||
} | |||
yield '解凍処理が完了しました'; | |||
} | |||
catch (\Exception $e) { | |||
yield "解凍処理中にエラーが発生しました: {$e->getMessage()}"; | |||
throw $e; | |||
} | |||
} | |||
/** | |||
* ファイルの存在確認と権限チェックを行うプライベートメソッド | |||
* | |||
* @param string $filePath チェック対象のファイルパス | |||
* @throws RuntimeException チェック失敗時 | |||
*/ | |||
function validateFile(string $filePath): void | |||
{ | |||
if (!file_exists($filePath)) { | |||
throw new RuntimeException("ファイルが存在しません: {$filePath}"); | |||
} | |||
if (!is_readable($filePath)) { | |||
throw new RuntimeException("ファイルの読み取り権限がありません: {$filePath}"); | |||
} | |||
if (!is_file($filePath)) { | |||
throw new RuntimeException("指定されたパスがファイルではありません: {$filePath}"); | |||
} | |||
} | |||
</syntaxhighlight> | |||
<br> | |||
<syntaxhighlight lang="php"> | |||
// 使用例 | |||
$decompression = new Utils\DecompressionUtils(); | |||
try { | |||
// 非同期処理の例 | |||
// ZIP形式の場合 | |||
foreach ($decompression->extractAsync('/path/to/archive.zip', '/path/to/destination', 'zip') as $status) { | |||
echo $status . PHP_EOL; | |||
} | |||
// tar.gz形式の場合 | |||
foreach ($decompression->extractAsync('/path/to/archive.tar.gz', '/path/to/destination', 'gz') as $status) { | |||
echo $status . PHP_EOL; | |||
} | |||
// tar.xz形式の場合 | |||
foreach ($decompression->extractAsync('/path/to/archive.tar.xz', '/path/to/destination', 'xz') as $status) { | |||
echo $status . PHP_EOL; | echo $status . PHP_EOL; | ||
} | } | ||