fgetcsv の代替関数

fgetcsv は便利な関数だが、Windowsデータとの連携に問題がある。

WindowsからCSVをアップロードする場合、Shift-JIS がほとんどだと思われる。
一方、fgetcsv関数はロケール設定を考慮するため、システムのロケールとCSVファイルの文字コードが一致していないと正しく解析されない。

色々調べたが、レンタルサーバでもしっかり動かすため、代替関数を作成した。

あきらはメインコントロールのクラスに定義している。

    
    // File Get CSV
    
    function fgetcsv( &$fh, $test = false ) {
        if ( feof( $fh ) ) return false ;
        
        $csv = '' ;
        
        while ( ! feof( $fh ) ) {
            $csv .= mb_convert_encoding( fgets( $fh ), 'UTF-8', 'SJIS-win' ) ;
            if ( ( ( preg_match_all( '/"/', $csv, $matches ) ) % 2 ) == 0 ) break ;
        }
    	
        $values = array() ;
        
        $temp = preg_replace( '/(?:x0Dx0A|[x0Dx0A])?$/', ',', $csv, 1 ) ;
        
        preg_match_all( '/("[^"]*(?:""[^"]*)*"|[^,]*),/', $temp, $matches ) ;
        
        for ( $i = 0 ; $i < count( $matches[ 1 ] ) ; $i++ ) {
            if ( preg_match( '/^"(.*)"$/s', $matches[ 1 ][ $i ], $m ) ) {
                $matches[ 1 ][ $i ] = preg_replace( '/""/', '"', $m[ 1 ] ) ;
            }
            
            $values[] = $matches[ 1 ][ $i ] ;
        }
        
        return $values ;
    }

クラス内で以下の様に使う。

    $fh = fopen( $path ) ;

    while ( ( $data = $this->fgetcsv( $fh ) ) !== false ) {
        ...
    }

    fclose( $fh ) ;

参考サイト :
Perlメモ – 値に改行コードを含む CSV形式を扱う
EthnaWiki – php/Tips/csv

1件のコメント

  1. まず、コードありがとうございます。

    ただ、コードをコピペしたとき、

    > $temp = preg_replace( ‘/(?:x0Dx0A|[x0Dx0A])?$/’, ‘,’, $csv, 1 ) ;

    の¥が普通の円マークではなくうまく動作せずにはまりました・・・。

    ¥をキーボードから普通に入力したら動きましたが。

コメントする

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

*

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください