いろいろあったのだけど、ようするに使えないということがわかった……。忘れないように書いとく。
PHPにfgetcsv()という便利関数があって。ファイルをCSVとして一行とりだして、各列の値を配列に入れて返すというものなんだが。
PHP4のはじめのころは、バグだらけなので有名だったらしいのだけど、さすがにPHP5.2なら大丈夫だろうと思ったら。しかしダメ。
マルチバイト文字の2バイト目に'\'があると、直後のダブルクォーテーションをエスケープするという、少なくともEXCELの仕様にはない独自解釈をするらしく。つまりSJISのファイルを読ませるとうまくいかない。
(ただし、EXCELがCSVをどう解釈するかという仕様は公開されてなさげ)
じゃあEUCに変換してから読ませれば、いちおうは大丈夫なんだけど、もちろん機種依存文字が化ける。 ←(これは指摘されたのでいちおう修正。SJIS-winからEUCJP-winとかUTF-8とかに変換すれば使える。けどめどい)
だいだいCSVを使うときというのはEXCELからくるデータなわけで。文字コードはSJISだし、機種依存文字も使いまくりがあたりまえだ。それがいけないのではあるけど、しかし対応するしかないし。
もしどうしても使うなら、あらかじめ機種依存文字を安全な文字列に変換して、EUCにして保存し、そのあとでファイルを開いてfgetcsv()するとか?(やる気にならないから試してない)もちろん、そんなことするなら自分で処理を書いたほうがいい。 ←(これもSJIS-winとか指定すれば特別な変換はいらない)
というわけで。もう二度と使わないぞ。
というわけで、できるだけExcelの動きに近づけてみた関数を作ってみたんだ。
調べてみると、セル中でダブルクォートが出てきたときとか、あんたほんとにそれでいいのかと思う動きをするけど、あくまでそんなExcelを再現しようとしてみる。
function fgetExcelCSV(&$fp , $length = null
, $delimiter = ',' , $enclosure = '"') {
$line = fgets($fp);
if($line === false) {
return false;
}
$bytes = preg_split('//' , trim($line));
array_shift($bytes);array_pop($bytes);
$cols = array();
$col = '';
$isInQuote = false;
while($bytes) {
$byte = array_shift($bytes);
if($isInQuote) {
if($byte == $enclosure) {
if($bytes[0] == $enclosure) {
$col .= $byte;
array_shift($bytes);
} else {
$isInQuote = false;
}
} else {
$col .= $byte;
}
} else {
if($byte == $delimiter) {
$cols[] = $col;
$col = '';
} elseif($byte == $enclosure && $col == '') {
$isInQuote = true;
} else {
$col .= $byte;
}
}
while(!$bytes && $isInQuote) {
$col .= "\n";
$line = fgets($fp);
if($line === false) {
$isInQuote = false;
} else {
$bytes = preg_split('//' , trim($line));
array_shift($bytes);array_pop($bytes);
}
}
}
$cols[] = $col;
return $cols;
}
つまりなにがいいたいかというと、
っていうかそんなの例外ケースなので、やる必要はまったくないけど(笑)
[2007.10.27 11:22]anonymous :
CSVファイルをSJIS-winからUTF-8に変換してから、
fgetcsv()を使用し、UTF-8からSJIS-winに戻せば
機種依存文字等も壊れないけどね。
※SJIS→EUCだと壊れる。
[2007.10.27 21:47]てらしま :
実際仕事ではそういうことやりましたが(笑) けっきょく、それでもExcelと動作が違っていると、いつか不具合といわれても不思議はないのが現実なんですよねえ。
[2007.10.28 01:12]てらしま :
というわけで、まあ指摘いただいたのでいちおう上の内容を修正しときます。
[2007.11.02 12:00]anonymous :
fgetExcelCSV()って、セル内に改行がある場合に対応してないのでは?
fgetcsv() はセル内に改行がある場合に対応してるけど…。
[2007.11.02 23:18]てらしま :
対応してるはずです。がやってみてうまくいかなかったら、なおすなりなおせというなりしてください。
うえき -2009/07/13 18:16
わかりやすいソースですね。このソース(fgetExcelCSV)のライセンスを教えてください。
サイトで使わせていただきたいと思っています。
てらしま -2009/07/13 19:16
……考えてもいなかったです。
なにをどうされてもかまわないです。とりあえずNYSL0.9982にしたがいます、ということでおねがいします。
うえき -2009/07/14 09:59
ありがとうございます。使わせていただきます。
Motty -2012/08/20 16:35
今だに fgetcsv に悩まされていました。
このページに救われました!
fgetExcelCSV使わせて頂きます。
有難うございます。
てらしま -2012/08/21 16:07
いやその、読んでいただいたのは嬉しいですが。
これはもう何年も前に書いたもので、しかも半分冗談の書き殴りコードです。使用はおすすめしません。
もっと新しくていいものがあるので、そちらを探してください。