🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
CSV

CSV(Comma-Separated Values)はコンマで区切られた明白なテキスト値のリストです。もしくは、そのフォーマットでひとつ以上のリストを含むファイルを指します。

PHP

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

文字コード

文字コードとは、文字や記号をコンピュータ上で使用するために用いられるバイト表現を指します。

Q&A

解決済

5回答

4840閲覧

PHPでのCSVファイルの読み込み時の文字化けについて

taniguchii

総合スコア2

CSV

CSV(Comma-Separated Values)はコンマで区切られた明白なテキスト値のリストです。もしくは、そのフォーマットでひとつ以上のリストを含むファイルを指します。

PHP

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

文字コード

文字コードとは、文字や記号をコンピュータ上で使用するために用いられるバイト表現を指します。

0グッド

0クリップ

投稿2021/01/06 01:32

PHP初心者です。

現在、PHPでCSVファイルをmove_uploaded_fileを使って読み込みたいと思っています。
その際に、CSVファイルをそのまま読み込んでみると見事に文字化けしてしまします。

文字化け対策としてmb_convert_encodingを使おうとしているのですが
これがうまくいきません。

ただそもそものCSVファイルをメモ帳で開いて、文字コードをUTF-8 で保存してから
読み込むと成功しています。
しかし、読み込みたいCSVファイルが大量にあるので
一つ一つ文字コードを変換して保存してから読み込むのはかなり手間がかかっしまうので
PHPのコードで文字コードを変換できたら、手間が一つ減ると思って
この方法を採用しようと考えています。

これが現在のコードです。

$upName=mb_convert_encoding("./uploads/".$_FILES['upfile']['name'], "UTF-8", "auto");

浅はかな知識なので第2因数は適当にUTF-8(メモ帳でUTF-8の文字コードを選択して読み込んだら成功したためこちらを選択)、第3因数はauto(これで大体は対応できると参照したサイトに書いてあったため)にしています。

他に試したことはmb_detect_encodingで現在の文字コードを調べてみようと思ったのですが
CSVファイルに様々な文字コードが使われているせいなのかは定かではありませんが、
うまく表示させることができませんでした。

手段としてできないことが、調べていて文字コードを調べる事ができる「サクラエディタ」という
ものがあることを知りましたが、諸事情のためこちらを使うことができません。

どなたかこちらの解決方法をご教授お願い致します。

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

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

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

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

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

hentaiman

2021/01/06 01:36

> auto(これで大体は対応できると参照したサイトに書いてあったため) の大体に入らなかっただけかもしれないのでひとつひとつ試してみてはどうでしょう?
m.ts10806

2021/01/06 01:37

具体的な文字コード入れたほうが良いでしょうね。
m.ts10806

2021/01/06 01:38 編集

そもそもPHPプログラムファイル自体の文字コードは何でしょうか。 それが分からない限り文字コード変換は完全手探りとなり、非効率にもほどがあります。
taniguchii

2021/01/06 01:41

具体的な文字コードというのは一体何を試したら良いのでしょうか。
taniguchii

2021/01/06 01:41

>そもそもPHPプログラムファイル自体の文字コードは何でしょうか。 UTF-8だと思われます。
m.ts10806

2021/01/06 01:45

>具体的な文字コード >思われます ですから、文字コードは確実に確認してください。 でなきゃ、存在する文字コードの組み合わせ全てを試すしかありません。 何通りあるかな。 http://lab.kiki-verb.com/mojibakeratta/
taniguchii

2021/01/06 01:56

PHPプログラムファイル自体の文字コードはUTF-8で間違いありませんでした。 試してみます。 わざわざありがとうございます。
m.ts10806

2021/01/06 01:57

"文字コードを調べる事ができる「サクラエディタ」という ものがあることを知りましたが、諸事情のためこちらを使うことができない" 状況でどのように確認されたのでしょうか。
taniguchii

2021/01/06 01:59

社用PCということがあってインストール権限がないのです。
hentaiman

2021/01/06 03:38

りなっくすのこまんどつかえばいいじゃんって思うけどきっとだめなんでしょうね さいしょにかいたひとつひとつ試すのはするーしてるみたいだけど試せないんですかね?
退会済みユーザー

退会済みユーザー

2021/01/06 03:58

CSVファイルの文字コードを特定できない限り、対応できません。 ファイルごとに文字コードがバラバラだとすると、PHPで対応できないんじゃないかな。
taniguchii

2021/01/06 07:25

返信遅くなり申し訳ございません。 結局全ての文字コードを試したのですが、うまく変換できませんでした。 もしかしたら対応していない文字コードだったのかもしれません。 CSVファイルの文字コードも特定できませんでした。 自分の力不足のせいでこれ以上どうすることもできず、全て元のファイルの文字コードを変換してから読み込むことにしました。 皆様の助力に対応しきれず申し訳ございません。
m.ts10806

2021/01/06 07:29 編集

ですから「文字コードを確実に確認してください」と言いました。 「おおよそこれだろうな」という予想はできても、それは単なる予想。 不確定要素が多い状態で確実なアドバイスはできません。 プログラムは書いたとおりにしか動かないので、代案として書いたものの「総当たり」はナンセンス以外なにものでもないです。何のためにプログラミングをしているのか?に反する行動ですし、手動で試したなら必ず抜けが出ます。 >社用PCということがあってインストール権限がないのです。 いえ「なぜインストールできないのか」を聞いているのではありません。 「サクラエディタすらインストールできない状況で、どうやってプログラムファイル自体の文字コードを確認したのか」と聞いています。 結局、文字コードが確認できるツールの使用は不可欠です。 もし、それができるならCSVだろうとなんだろうと文字コードの確認はできます。
taniguchii

2021/01/06 07:44

プログラミングはeclipseを使っているのですが、eclipseの設定を開いて文字コードは確認しました
m.ts10806

2021/01/06 07:52

でしたら、CSVだろうとなんだろうと文字コードの確認はできるはずです。 ファイルを選択状態で右クリックプロパティ。
guest

回答5

0

https://qiita.com/wakabadou/items/36dd08f6a51fcafab2b1
こちらのライブラリをご利用ください。
現時点において恐らくただ一つの完全な解決手段です。

他の回答にある対応・記事はこちらの記事にある通り、何かしら問題があり、完全な解決にはなりません。
https://qiita.com/wakabadou/items/84b48ca12f25fb2fb69c

それと別件ですが、アップロード直後のファイルを扱うのならば、$_FILES['upfile']['name']を使うのは不適です。
$_FILES['userfile']['tmp_name']を使用しましょう。

php

1$rows = StreamFilterSpec::decorateForCsv(function () { 2 //============================================== 3 // 読み込み 4 //============================================== 5 // フィルタの設定 6 $spec = StreamFilterSpec::resource($_FILES['userfile']['tmp_name'])->read([ 7 StreamFilterConvertEncodingSpec::toUtf8(), 8 ]); 9 10 // \SplFileObjectでも使用できます。 11 $rows = []; 12 13 $fp = \fopen($spec->build(), 'r+b'); 14 while (($row = \fgetcsv($fp, 1024)) !== FALSE) { 15 $rows[] = $row; 16 } 17 \fclose($fp); 18 19 return $rows; 20});

なお、日本語環境において自動でエンコーディング検出を行う場合は次の設定が正解です。
今後使う機会があるかもしれないので、覚えておくと良いかもしれません。

php

1// 期待通りに動作する検出順 2$detect_order = [ 3 'eucJP-win', 4 'SJIS-win', 5 'JIS', 6 'ISO-2022-JP', 7 'UTF-8', 8 'ASCII', 9]; 10 11// エンコーディングを検出する場合 12$encoding = \mb_detect_encoding($string, $detect_order, true); 13 14// エンコーディング変換 15$string = \mb_convert_encoding($string, 'UTF-8', $detect_order);

投稿2021/01/06 13:27

wakabadou

総合スコア31

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

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

0

fgetcsvで配列に受け取ってmb_convert_variablesを試してみて下さい

投稿2021/01/06 02:06

yambejp

総合スコア116661

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

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

0

autoなんて当てになりません。
autoにしたときの判定基準については、
php.iniのmbstring.detect-orderに依存します。
実行時にmb_detect_orderを使って介入してもいいです。
autoを使いたいならmb_detect_order()でSJIS-winを優先させれば良いかもしれません。

Excelで出力したものであれば、
SJIS-win
から変換するってことで良いかと。
(SJISのみでは、機種依存文字がつぶれます)

PHP: サポートされる文字エンコーディング - Manual


この事例を真似してください。
PHP: fgetcsvでもSJISのCSVをUTF-8として《安全》に読む方法(ストリームフィルタ使用) - Qiita

この方法も良いです。
[PHP] SJISのCSVファイルの文字化けせずに読み込む方法(SplFileObject) | マリンロード

投稿2021/01/06 01:53

編集2021/01/06 04:12
退会済みユーザー

退会済みユーザー

総合スコア0

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

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

0

ええと、先にあげた回答のライブラリを使うと、投入するファイルの文字コードがそれぞれ異なっていても全て適切に扱えます。

ライブラリが適切にエンコーディングを検出でき、正しいやり方でfgetcsvを起動できるので、世間一般で言われているfgetcsvにまつわる読み込み失敗問題が起きないためです。

他の方の回答でも言われている通り、手介入時にデータが変わってしまうリスクを考えると、ちゃんと実装を行ったほうが良いと思います。

投稿2021/01/08 08:30

wakabadou

総合スコア31

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

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

0

自己解決

いろいろな解決方法を提示してくれた方々ありがとうございました。
そして一切返信を返していなくて申し訳ございませんでした。

結論から言いますと、一つ一つファイルの文字コードを変換して
保存することになりました。

最初はかなりのデータがあるためにこの方法ができない(したくない)と
言っていたのですが、これは1日1個のデータが1年分あったからなのですが
これが月終わりに1つのデータとしてまとめているものがあったらしく
365個のデータが12個のデータに減ったので手作業での変換でも
対応可能になったからです。

まだまだ初心者なので皆様のアドバイスの理解するのでもかなりの時間が
かかっており、返信するも何も解決していなかったからということを
言い訳になってしまうのですが報告させていただきます。

改めて色々アドバイスをしてくれた方々に感謝しています。
また時間はかかってしまうと思いますが、今回回答させて頂いたものは
今後のために勉強していこうと思います。

投稿2021/01/08 06:41

taniguchii

総合スコア2

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

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

退会済みユーザー

退会済みユーザー

2021/01/08 06:56

365個のファイルがでたらめにエンコーディングが違う、 なんてことは(勝手に誰かが編集でもしない限り)ふつう考えられないし、 どうせ(Excelを含めた)何かのシステムやソフトから出力したものなのでしょうから、 あるパターンで処理してうまく行ったものと失敗したものを仕分けして、 失敗したものについて別のアプローチを試みる、っていうふうにして収束を試みるといいんじゃないかなって思いました。 (むしろ、手介入しちゃってエンコーディングが変わっちゃうのも良しとしてしまうと、システムにならんのです。) また、出力するシステムの作りが雑だと、CSVファイルの規則性を壊すようなデータ出力、 例えば”~"の「"」を忘れたり文字列内に埋め込んでいたり「,」が含まれている数値だったりと おかしなことになっている場合もあります。 例えばこういうのはどうですか。 "aaa","b"b"b","1,234" 自前でCSV文字列からデータの切り出し処理を起こそうとすると、 そういうイレギュラー対応をどこまでがんばるかっていう不安要素が拭えません。 そんな不安要素をある程度肩代わりしてくれるのが、 fgetcsvだったりSplFileObjectのREAD_CSVだったりしますが、 本当にぶっ壊れている構造だとそういう高級な関数でもダメなので、 その時は自前で処理を起こすしかなくなります。 機会があればCSV読み込み処理にチャレンジしてみるといいです。 そもそもCSV文字列自体が完璧なデータ構造じゃないし 出力側と入力側の阿吽の呼吸が求められるんだぞっていうのが、 わかっていただけると思います。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.36%

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

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

質問する

関連した質問