質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
Linux

Linuxは、Unixをベースにして開発されたオペレーティングシステムです。日本では「リナックス」と呼ばれています。 主にWebサーバやDNSサーバ、イントラネットなどのサーバ用OSとして利用されています。 上位500のスーパーコンピュータの90%以上はLinuxを使用しています。 携帯端末用のプラットフォームAndroidは、Linuxカーネル上に構築されています。

Windows

Windowsは、マイクロソフト社が開発したオペレーティングシステムです。当初は、MS-DOSに変わるOSとして開発されました。 GUIを採用し、主にインテル系のCPUを搭載したコンピューターで動作します。Windows系OSのシェアは、90%を超えるといわれています。 パソコン用以外に、POSシステムやスマートフォンなどの携帯端末用、サーバ用のOSもあります。

PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

CakePHP

CakePHPは、PHPで書かれたWebアプリケーション開発用のフレームワークです。 Ruby on Railsの考え方を多く取り入れており、Railsの高速性とPHPの機動性を兼ね備えています。 MVCやORMなどを「規約優先の考え方」で利用するため、コードを書く手間を省くことができます。 外部のライブラリに依存しないので、単体での利用が可能です。

zip

ZIPとは、複数のファイルをひとつにまとめて圧縮したり、圧縮したファイルを展開することができるアーカイブフォーマットです。 1998年以降のWindowsOS各バージョンで、標準の圧縮フォルダとして採用されています。 MacOSでも、X v10.3以降に他の圧縮ソフトとまとめてZIP機能を採用しています。

Q&A

解決済

4回答

26711閲覧

php zipArchiveを利用したときに日本語が文字化けしてしまう(windowsで圧縮したファイルをlinuxで解凍した場合)

test_87097

総合スコア45

Linux

Linuxは、Unixをベースにして開発されたオペレーティングシステムです。日本では「リナックス」と呼ばれています。 主にWebサーバやDNSサーバ、イントラネットなどのサーバ用OSとして利用されています。 上位500のスーパーコンピュータの90%以上はLinuxを使用しています。 携帯端末用のプラットフォームAndroidは、Linuxカーネル上に構築されています。

Windows

Windowsは、マイクロソフト社が開発したオペレーティングシステムです。当初は、MS-DOSに変わるOSとして開発されました。 GUIを採用し、主にインテル系のCPUを搭載したコンピューターで動作します。Windows系OSのシェアは、90%を超えるといわれています。 パソコン用以外に、POSシステムやスマートフォンなどの携帯端末用、サーバ用のOSもあります。

PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

CakePHP

CakePHPは、PHPで書かれたWebアプリケーション開発用のフレームワークです。 Ruby on Railsの考え方を多く取り入れており、Railsの高速性とPHPの機動性を兼ね備えています。 MVCやORMなどを「規約優先の考え方」で利用するため、コードを書く手間を省くことができます。 外部のライブラリに依存しないので、単体での利用が可能です。

zip

ZIPとは、複数のファイルをひとつにまとめて圧縮したり、圧縮したファイルを展開することができるアーカイブフォーマットです。 1998年以降のWindowsOS各バージョンで、標準の圧縮フォルダとして採用されています。 MacOSでも、X v10.3以降に他の圧縮ソフトとまとめてZIP機能を採用しています。

0グッド

1クリップ

投稿2015/10/14 08:30

編集2015/10/15 03:58

初めて質問させて頂きます。

現在やろうとしていることは、ZIPファイルをweb上でアップロードして解凍する機能を作っています。

そこでzipArchiveクラスを使おうと考えたのですが、linuxで圧縮したzipファイルは問題ないのですが、windowsで圧縮したzipファイルだと日本語部分が文字化けしてしまいます。

エンコーディングをUTF-8に変更したり、linux側のlocaleも変更したのですが、それでも日本語部分の文字化けが直りませんでした。

windowsで圧縮されたzipファイルの日本語部分を文字化けすることなく解凍するための方法を教えて頂きたく質問しました。

コードを載せますので、ぜひご教授ください。

public function extractionZip($data = null, $destDir = TMP, $toEncoding = 'UTF-8') { if (setlocale(LC_ALL, 'ja_JP.UTF-8') === false) { error_log('Locale not found: ja_JP.UTF-8'); exit(); } $zip = new ZipArchive; $zipFile = TMP . 'zip/' . $data['Zip']['name']; $hex = file_get_contents($zipFile, false, null, 7, 1); $fromEncoding = (ord($hex) & 0x08) === 0x08 ? 'UTF-8' : 'CP932'; $sameEncoding = $fromEncoding === $toEncoding; $res = $zip->open($zipFile); if ($res === false){ return false; exit(); } $num_files = $zip->numFiles; for ($i = 0; $i < $num_files; $i++) { $stat = $zip->statIndex($i); $name = $sameEncoding ? $stat['name']: mb_convert_encoding($stat['name'], $toEncoding, $fromEncoding); if ($name[strlen($name)-1] === '/') { continue; } $splited = explode('/', $name); $baseName = array_pop($splited); $dir = empty($splited) ? $destDir. implode('/', $splited). '/' : $destDir ; if (is_dir($dir) === false) { mkdir($dir, 0777, true); } file_put_contents("{$dir}{$baseName}", $zip->getFromIndex($i), LOCK_EX); } $dir = $zip->extractTo(TMP . 'zip'); $zip->close(); }

ご回答を参考にして書いたコードです。解凍はするのですが、ディレクトリ名が日本語だと文字化けし、圧縮したファイル名が日本語だとそれも文字化けします。英語やlinuxで圧縮したファイルであれば問題ありません。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答4

0

ベストアンサー

php

1$zipFile = mb_convert_encoding($zipFile, 'UTF-8', 'SJIS-win');

from を明示しないと意図した動作になりません。

mb_convert_encoding

変換前の文字エンコーディング名を指定します。 これは、配列またはカンマ区切りの文字列とすることが可能です。 from_encoding を指定しなかった場合は、内部文字エンコーディングを使用します。

内部文字エンコーディング = 実行しているPHPのエンコーディング(=UTF-8)


追記)2015/10/16

自前のフレームワークでも出番があるかもしれないので、作ってみました。
ただし、手元の開発環境にWindowsがないため、正しい動きになるかどうかはわかりません。
一応、エラーはなく動くことは確認していますが…。

php

1<?php 2 3/** 4 * Archive.class.php 5 */ 6class Archive 7{ 8 9 /** 10 * Windows で作成された SJIS-WIN のファイル名を含む ZIP ファイルを UTF8 に変換する 11 * @param string $archive 12 * @param string $to 変換後エンコード 13 * @param string $from 変換前エンコード 14 * @return array 置換結果を配列で返す 15 */ 16 public static function convertZipEncode($archive, $to = 'UTF-8', $from = 'CP932') 17 { 18 $zip = new \ZipArchive; 19 $res = array(); 20 if ($zip->open($archive) === TRUE) { 21 $idx = 0; 22 while ($zip->statIndex($idx)) { 23 $zipEntry = $zip->statIndex($idx); 24 $entryName = $zipEntry['name']; 25 $destName = mb_convert_encoding($zipEntry['name'], $to, $from); 26 $zip->renameName($entryName, $destName); 27 $zip->extractTo('.', $destName); 28 $zip->renameName($destName, $entryName); 29 $res[] = array('from' => $entryName, 'to' => $destName); 30 $idx++; 31 } 32 $zip->close(); 33 return $res; 34 } 35 return false; 36 } 37 38} 39 40

php

1<?php 2 3require_once './Archive.class.php'; 4 5$archive = 'ファイルのパス'; 6$res = Archive::convertZipEncode($archive); 7var_dump($res);

投稿2015/10/14 08:35

編集2015/10/15 20:47
退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

test_87097

2015/10/14 09:18

ご回答ありがとうございます。ご教授頂いた通りにfromを指定してみたのですがうまく行きませんでした。 そもそもですが、mb_convert_encodingするまえの$zipFile をmb_detect_encodingで調べてみるとUTF-8になっていました。ここのエンコードがUTF-8でないから解凍した際に文字化けを起こすと思っていたのですが、他に問題があるようです汗
退会済みユーザー

退会済みユーザー

2015/10/14 09:54

> UTF-8になっていました ???そうであれば文字化けはしないはず・・・
test_87097

2015/10/14 10:04

そうですよね。その通りなのですが、linuxで圧縮したファイルは文字化けせずにwindowsで圧縮したファイルは日本語の部分だけどうしても文字化けしてしまいます。
退会済みユーザー

退会済みユーザー

2015/10/14 10:19

ああ、なるほど… エンコーディングをしなければいけないのは、ZIPの中のファイルです。 ZIPファイルではなくて。 例えば、windows で、サンプル.txt を圧縮した ジップ.zip を作成したとしますね。 このとき、Windows上ではどちらのファイルもSJIS-WIN(CP932)の文字コードです。 サーバーにアップロードされた時、PHPで直接操作できるのは、ジップ.zip だけで、サンプル.txt は操作できません。 1,サーバーにアップロード 2,サーバーはZIPをとにかく展開する 3,展開されたディレクトリを走査して全てのファイル名をUTF-8にエンコーディング 4,エンコーディングしたファイルをZIPに圧縮 というようにすれば、UTF-8 のZIPが完成します。
test_87097

2015/10/15 03:26

ご回答ありがとうございます。 アップロードされた時に直接操作出来るのはzipファイルだけで中身までは出来ないのですね。 流れは理解出来たのですが、自分のプログラミング技術が未熟なため、なかなかうまくいきません。 2番で展開した際に文字化けしてしまうので、エンコーディングをしてもUTF-8にはなるのですが、文字化けは継続したままになってしまいます。 それとzipファイルはエンコーディングされているのであれば、展開された時のディレクトリ名は文字化けしないような気がするのですが、そこも文字化けしてしまうのです。
退会済みユーザー

退会済みユーザー

2015/10/16 05:09

追記しました
test_87097

2015/10/16 09:01

追記ありがとうございます。書いて頂いたコードを参考にし何とか目的通りの動きをするコードが書けました。とても一人では今回の件は解決出来なかったと思います。 本当にありがとうございました。
退会済みユーザー

退会済みユーザー

2015/10/16 09:05

> 書いて頂いたコードを参考にし何とか目的通りの動きをするコードが書けました。 ぜひ、これで終わるのではなく、他の回答者のためにも、最終的にどのようなコードになったのかフィードバックをお願いします。
guest

0

私も最近これとまったく同じ壁にあたり、どうしても解決できなかったので、
ある意味裏技ですがwineを使用して解決しました。
wineはUnix(Linux)OS上でWindowsアプリケーションを動作させるために開発されたソフトウェアです。
私の場合、wine+7zipのコマンドライン版を使用して、アップロードされたZIPファイルを解凍させています。
結果的に、どうしても文字化けしていた日本語ファイル名も正常に解凍できています。

wineを使用することでwineプロセス起動+エミュレーション上での7zip起動と、パフォーマンス的にはお世辞にも良いとは言えないので、ケースによっては使えるかもしれません。

あくまでそういう手もあるよ。ということで。
wine wikipedia
7zip コマンドライン版

投稿2015/10/15 14:37

編集2015/10/15 14:38
TakuyaMitamura

総合スコア74

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

test_87097

2015/10/16 08:59

ご回答ありがとうございます。 今回は何とかzipArchiveでプログラミング出来たのですが、またパターンが変われば出来なくなることもあると思いますので、その際にはwine+7zipのコマンドライン版を利用してみようと思います
guest

0

ご教授して頂いたことを参考になんとか動くコードを書けました。

投稿2015/10/16 09:02

test_87097

総合スコア45

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

文字化けと言っているのは、展開した後のフォイル名が日本語の場合だと文字化けするという話であっていますでしょうか?これはZIPのフォーマットそのものの問題であるため、簡単な解決方法はありません。

ZIP内部では圧縮されたファイルのファイル名が保存されていますが、文字コードについてフォーマット上の規定がありません。そのため、Windowsでは実行時ロケールのANSIコード(日本語環境のWindowsであればShift_JISの亜種であるCP932になります)でエンコードしてファイル名を保存します。それに対して、MacやLinuxもロケールのエンコードになりますが、最近の環境では通常UTF-8になりますので、UTF-8でファイル名を保存します。そのため、Windowsで作成したZIPを展開した場合、CP932でエンコードされた文字列をそのまま展開するため、UTF-8環境のLinux上では文字化けしてしまいます。

では、どうするかというと、一気に展開せずに、ファイル一個一個のファイル名をCP932からUTF-8に変換しながら、変換したファイル名で保存する形で展開していきます。詳しいやり方は、同じ問題を解決している人がいたので、下記を参考にしてみてください。
Qiita: ZipArchiveで日本語ファイル名を扱えない場合があって困った話

投稿2015/10/14 10:39

raccy

総合スコア21733

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

test_87097

2015/10/15 03:30

ご回答ありがとうございます。 教えて頂いたページを参考にコードを作って見たのですが、file_get_contentsで思うような結果が出ずに、1つ1つエンコーディングを行っても文字化けしてしまった状態で行うので文字化けしたままUTF-8になってしまいます。エンコーディングしながらファイル名を保存出来ていないようです。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問