LoginSignup
1

More than 5 years have passed since last update.

Excelから保存したUnicodeテキストを読み込む

Last updated at Posted at 2016-02-10

CSVではなくUnicodeテキストを読み込みたい

ExcelでShift_JIS外の文字を扱っている場合、Excelからcsv書き出しした時点で文字が?に置換されて消えてしまいます。保存形式を「Unicodeテキスト」にすると、文字が消えずUnicodeのタブ区切りテキスト(tsv)で書き出されます。

これをPHPで読み込むのに、意外とハマったのでメモです。

ソースコード

<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>Excelから保存したUnicodeテキストのアップロード</title>
</head>

<body>
<p>Excelから保存したUnicodeテキストのアップロード</p>
<form action="" method="post" enctype="multipart/form-data">
    <input type="file" name="tsvfile">
    <button type="submit">送信</button>
</form>
<p>
<?php
$err_msg = '';

//データを格納する配列
$tsvdata = array();

if (is_uploaded_file($_FILES["tsvfile"]["tmp_name"])) {
    $file_tmp_name = $_FILES["tsvfile"]["tmp_name"];
    $file_name = $_FILES["tsvfile"]["name"];
    //文字コード指定
    setlocale(LC_ALL, 'ja_JP.UTF-8');
    //拡張子を判定
    if (pathinfo($file_name, PATHINFO_EXTENSION) != 'txt') {
        $err_msg = '拡張子txtのUnicodeテキストファイルのみ対応しています。';
    } else {
        //UTF-16からUTF-8へ変換
        $buffer = file_get_contents($file_tmp_name);
        file_put_contents($file_tmp_name, mb_convert_encoding($buffer, 'UTF-8', 'UTF-16'));
        unset($buffer);
        //変換がおわったら、ファイルを読み込む
        $fp = fopen($file_tmp_name, "r");
        //区切り文字にタブを指定して配列に格納していく
        while (($data = fgetcsv($fp, 0, "\t")) !== FALSE) {
            if(count($data)==4){
                //カラム数が4列の場合のみデータに追加する
                $tsvdata[] = $data;
            }
        }
        fclose($fp);
    }
    //---処理終了---
    if($err_msg == ''){
        //簡易表示チェック
        echo '<table border="1">';
        for($cnt1=0;$cnt1<count($tsvdata);$cnt1++){
            echo '<tr>';
            for($cnt2=0;$cnt2<count($tsvdata[$cnt1]);$cnt2++){
                echo '<td>'.nl2br($tsvdata[$cnt1][$cnt2]).'</td>';
            }
            echo '</tr>';
        }
        echo '</table>';
    }else{
        //エラーメッセージ表示
        echo $err_msg;
    }
}
?>
</p>
</body>
</html>

ポイント

  • Excelから書き出す「Unicodeテキスト」の文字コードは「UTF-16」である。そして、UTF-16は、 mb_detect_encoding() では判別できない。
  • setlocale(LC_ALL, 'ja_JP.UTF-8'); をしないと、一部の文字が表示されない現象があった。

参考にさせていただいた記事など

Qiita : PHPでCSVファイルをアップロードする(そして配列に変換)
Qiita : CSVアップロードからのMySQLへのデータ挿入
PHPマニュアル : mb_detect_order ※UTF-16はエンコーディング検出できない

さいごに

  • たぶんエラー処理など甘い気がしますが、何か気づいた点などがあればご指摘ください。

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
1