LoginSignup
5
5

More than 5 years have passed since last update.

fgetcsvを使ってSJISのCSVをロードするとき

Last updated at Posted at 2016-04-14

SJISのファイルをUTF8のDBにロードする目的でした。

失敗する可能性が高い例

何も考えないで書くと、こんな感じにデータを入れる直前で文字列変換するように書いてしまいがちですが、これだと文字化けで改行が崩れたりします。

hoge.php
$fp = fopen("example.csv", 'r');
while ($data = fgetcsv($fp, 10000)) {
  foreach( $data as $index=>$value) {
    // カラムごとにUTF8に変換
    $data[$index] = mb_convert_encoding($value, "UTF-8", "SJIS");
  }
  // DBにinsertとかupdateとか
}

fgetcsvで1行フェッチしてcsvをパースして配列に入れるタイミングで、まだ文字コードSJISのままです。

この操作でCSVの行が次の行とくっついたりしてハマることがあります。それを回避するために文字エンコーディングを変換してから一行ずつ読むように処理を変更します。

正しくパースできるようにする

fgetcsvが1行を読む時(ストリームを読むとき)に文字コードを変換しつつ読み出すフィルターを設定します。

フィルタは、php_user_filterというクラスをExtendして実装しないといけないのですが、その実装は、すでに先人の皆々さまによって用意していただいているものを拝借。最高。

stream_filter_register — ユーザー定義のストリームフィルタを登録する
http://php.net/manual/ja/function.stream-filter-register.php

Stream_Filter_Mbstring
http://openpear.org/#stream_filter_mbstring

クラスの中身はこちらと同じかな?

github : Stream_Filter_Mbstring - mbstringを使って文字列変換を行うstream filter
https://github.com/xcezx/Stream_Filter_Mbstring/blob/master/src/Stream/Filter/Mbstring.php

実装はこのようになります。

hoge.php

stream_filter_register('convert.mbstring.*','Stream_Filter_Mbstring');

$fp = fopen("example.csv", 'r');

stream_filter_append($handle,'convert.mbstring.encoding.SJIS-win:UTF-8');

while ($data = fgetcsv($fp, 10000)) {
  // もうUTF8になってるからそのままDBにinsertとかupdateとかできるよ
}

クラス1つなので、コピペしておこうかと思ったんですが(PEAR久し振りだからちょっとだるい)、折角composerでライブラリ管理しているので、composerからopenpear経由で管理するようにしましたが、これがはまりました…。

Composerでライブラリの追加

コレを実行。

composer config repositories.0 "pear" "http://openpear.org"
composer require "pear-openpear.org/Stream_Filter_Mbstring" "0.0.7"

…といけば、万々歳だったのですが、ハマりました。エラーメッセージはこんなで、どうやらhttpsでロードしたほうがいいよといっているようです。

エラーでた

hoge.txt
$ composer require "pear-openpear.org/Stream_Filter_Mbstring" "0.0.7"

./composer.json has been updated
Loading composer repositories with package information

Initializing PEAR repository http://openpear.org
PEAR repository from http://openpear.org could not be loaded. Your configuration does not allow connections to http://openpear.org/channel.xml. See https://getcomposer.org/doc/06-config.md#secure-http for details.
Updating dependencies (including require-dev)
Your requirements could not be resolved to an installable set of packages.

  Problem 1
    - The requested package pear-openpear.org/stream_filter_mbstring could not be found in any version, there may be a typo in the package name.

Potential causes:
 - A typo in the package name
 - The package is not available in a stable-enough version according to your minimum-stability setting
   see <https://getcomposer.org/doc/04-schema.md#minimum-stability> for more details.

Read <https://getcomposer.org/doc/articles/troubleshooting.md> for further common problems.

Installation failed, reverting ./composer.json to its original content.

そこで、repositorieshttps://openpear.org としても、チャンネルファイルのリンクが http://openpear.org/channel.xml となっていて、http:// のままなので、同じエラーが出ます。

エラー解決した

composerの設定でsecure-httpをoffにすることで解決しました。
あまり良くないけどしょうがないかなって。

composer config secure-http false

こレを実行した後、composer requireとかやると、ちゃんとインストールされます。

参考にさせていただいたのはこちら

巨大なSJISのCSVファイルをfgetcsv関数で処理する

ComposerでOpenpearのパッケージをインストールする方法

5
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
5