ホームページ >バックエンド開発 >PHPチュートリアル >CSVファイルをPHPにインポートする際に文字化けが発生する問題を解決する方法

CSVファイルをPHPにインポートする際に文字化けが発生する問題を解決する方法

不言
不言オリジナル
2018-07-03 16:15:082889ブラウズ

この記事では、CSV ファイルを PHP にインポートする際に発生する文字化けの問題の解決方法を主に紹介します。必要な友人は参考にしてください。

今日は主に、CSV ファイルを PHP にインポートする方法を書きたいと思いますPHP. 実際、インターネットでの検索はよく行われます。すべてインポート方法で実装できます。しかし、インポート時に 2 つの問題が発生し、1 つは Windows でコードを書くときにテストで文字化けが発生するという問題でしたが、その後解決されました。 2つ目は、Linuxシステムに送信したところ、また文字化けが発生したことです。最初はコードが文字化けする理由が分かりませんでした。最初は、コード svn の送信時のエラーだと思いました。最終的には、グループの 1 つで質問しました。私の友人は phpcms で働いています。 Windows からの svn のサブミットでエラーが発生し、Linux にサブミットすると最初は必ずエラーが発生し、後で文字化けが原因であることが判明したとのこと。早速本題に入り、これら 2 つの問題を解決する方法を見てみましょう。

問題の解決策:

PHP で csv ファイルを読み込むと、Windows では中国語が読み込めないので、すぐに mb_convert_encoding() という関数を思いつき、次のように設定します $str = mb_convert_encoding ( $str, "UTF-8", "GBK"); それで終わりです。もちろん、次のように iconv(); を使用して iconv('GBK',"UTF-8//TRANSLIT//IGNORE",$str); を設定することで Windows の文字化け問題を解決することもできます。

問題 2 の解決策:

PHP は csv ファイルを読み取りますが、Linux では中国語を読み取ることができません。Baidu と Google の後に解決策を見つけました。

追加しました。 1 行のコード setlocale(LC_ALL, 'zh_CN'); はい、目がくらむでしょう。非常に簡単なので、知らなかった場合は、理解するのに多くの時間を費やすことができます。

PHP setlocale()関数の説明

定義と使い方

setlocale()関数は、地域情報(地域情報)を設定します。

地域情報とは、地理的エリアの言語、通貨、時刻、その他の情報です。この関数は現在のロケールを返すか、失敗した場合は false を返します。

データ収集に一般的に使用される領域識別子は次のとおりです。

zh_CN GB2312 
en_US.UTF-8 UTF-8 
zh_TW BIG5 
zh_HK BIG5-HKSCS 
zh_TW.EUC-TW EUC-TW 
zh_TW.UTF-8 UTF-8 
zh_HK.UTF-8 UTF-8 
zh_CN.GBK GBK

たとえば、
utf-8: setlocale(LC_ALL, 'en_US.UTF-8');
簡略化: setlocale(LC_ALL, 'zh_CN');

setlocale() 関数について説明する理由は、csv ファイルを Linux システムにインポートしたときに、次のような文字化けが発生したためです。 mb_convert_encoding() 関数と iconv() 関数を使用しても、最終的な問題は解決できませんでした。最後に、csv ファイルのインポートの最初のコードの前に setlocale(LC_ALL, 'zh_CN'); という文を追加しましたが、これは簡単に完了しました。ロケール設定。たとえば、LANG が en_US.UTF-8 に設定されている場合、シングルバイトでエンコードされたファイルは読み取りエラーが発生するため、カルチャを設定する必要があります。特別にみんなと共有します。

次のコードも試してみましたが、取得できませんでした。これらは、csv ファイルを生成するためのヘッダー設定です。私にはうまくいかないかもしれませんが、あなたにはうまくいくかもしれません。そこで私は、CSV ファイルをインポートするときに文字化けに遭遇した同僚を助けるために、それを整理し、他に方法がない場合に対処するのが非常に困難だったため、最善を尽くしました。誰でも試してみましょう!あなたに属するものは常にあります。

<?php 
$csvContent="csvzero,csvone,csvtwo,csvthree,csvfour,csvfive"; 
header("Content-Type: application/vnd.ms-excel; charset=GB2312"); 
header("Pragma: public"); 
header("Expires: 0"); 
header("Cache-Control: must-revalidate, post-check=0, pre-check=0"); 
header("Content-Type: application/force-download"); 
header("Content-Type: application/octet-stream"); 
header("Content-Type: application/download"); 
header("Content-Disposition: attachment;filename=CSV数据.csv "); 
header("Content-Transfer-Encoding: binary "); 
$csvContent = iconv("utf-8","gb2312",$csvContent); 
echo $csvContent; 
exit; 
?>

CSV ファイルをインポートするための PHP のコードを詳しく見てみましょう:

2 つの関数の簡単な紹介、

によって検出される文字エンコーディングmb_detect_encoding() 、または指定された文字列のエンコーディングが検出できない場合は FALSE を返します。

fgetcsv() 関数は、ファイル ポインターから行を読み取り、CSV フィールドを解析します。 fgets() と似ていますが、 fgetcsv() は読み取った行を解析し、CSV 形式でフィールドを見つけ、それらのフィールドを含む配列を返す点が異なります。 fgetcsv() は、ファイルの終わりに達した場合など、エラーが発生した場合に FALSE を返します。

注: PHP 4.3.5 以降、 fgetcsv() の操作はバイナリ セーフです。

注: CSV ファイル内の空行は、単一の null フィールドを含む配列として返され、エラーとして扱われません。

注: この関数はロケール設定の影響を受けます。たとえば、LANG が en_US.UTF-8 に設定されている場合、シングルバイトでエンコードされたファイルには読み取りエラーが発生します。

注: ファイルの読み取り時に PHP が Macintosh ファイルの行末文字を認識できない場合は、auto_detect_line_endings ランタイム構成オプションをアクティブにすることができます。

<?php 
setlocale(LC_ALL, &#39;zh_CN&#39;); //设置地区信息(地域信息) 
$file = $_FILES[&#39;files&#39;]; 
$file_type = substr(strstr($file[&#39;name&#39;],&#39;.&#39;),1); 
if ($file_type != &#39;csv&#39;){ 
echo "<script type=\"text/javascript\">alert(\"文件格式错误,请重新上传!\"); </script>"; 
exit; 
} 
$handle = fopen($file[&#39;tmp_name&#39;],"r"); 
$file_encoding = mb_detect_encoding($handle); 
if ($file_encoding != &#39;ASCII&#39;){ 
echo "<script type=\"text/javascript\">alert(\"文件编码错误,请重新上传!\"); </script>"; 
exit; 
} 
$row = 0; 
$str=""; 
$sy=""; 
while ($data = fgetcsv($handle,1000,&#39;,&#39;)){ 
$row++; 
if ($row == 0) 
continue; 
$num = count($data); 
for ($i=0; $i<$num; $i++){ 
$str = (string)$data[$i].&#39;|&#39;; 
$str = mb_convert_encoding($str, "UTF-8", "GBK"); //已知源码为GBK,转换为utf-8 
$sy .= $str; //我这里做的比较复杂,是用&#39;|&#39;将csv文件里面的内容用&#39;|&#39;全部拼起来,因为我导入的是商品信息,需要根据用户需 
//要导入的数据去定义哪些数据是需要导入的。 
} 
} 
if ($sy) { $sy = rtrim($sy, &#39;|&#39;); } 
$arr = explode(&#39;|&#39;,$sy); 
$key = array_slice($arr,0,$num); //这个数组就是csv文件里面标题,就是商品id,标题,卖点等等的数据 
$skey = array(); 
$length = array(); 
$co = count($arr); 
$p = $co/$num; //求出要取出的数据的长度 
for($j=0;$j<$p;$j++){ 
$offset=($j-1)*$num; //偏移量,就像分页一样,我这里根据偏移量取出的一个数组就是一个商品的信息。 
if($j==0){ 
$length[] = array_slice($arr,0,$num); 
}else{ 
$length[] = array_slice($arr,$num+$offset,$num);//取出有哪些字段和商品 
} 
} 
$arrtitle = array(); 
$arrfileds = array(); 
$arrtagname = DB::select(&#39;字段标识&#39;, &#39;字段名称&#39;)->from(&#39;字段表&#39;)->fetch_all(); 
foreach ($arrtagname as $value) { 
$arrfileds[$value[&#39;fileds_tags&#39;]] = $value[&#39;fileds_name&#39;]; 
} 
foreach ($fileds as $v) 
{ 
$temarr= explode(&#39;-&#39;, $v); 
if (isset($temarr[0]) && !empty($temarr[0])) { 
if (isset($temarr[1]) && !empty($temarr[1])) { 
if ($temarr[1] == &#39;wenben&#39;) { 
$arrtitle[] = $arrfileds[$temarr[0]].&#39;文本&#39;; 
} 
} else { 
if ($temarr[0] != &#39;pic&#39;) { //是取出字段是图片就给去掉 
$arrtitle[] = $arrfileds[$temarr[0]]; 
} 
} 
} 
} 
$skey = array(); 
$order = array(); 
$order[] = &#39;act_tag&#39;; 
$order[] = &#39;channel_tag&#39;; 
$order[] = &#39;created_time&#39;; 
$order[] = &#39;orderby&#39;; 
$rows =&#39;&#39;; 
$f = $co/$num;//求出有多少件商品 
for($p=0;$p<count($arrtitle);$p++){ 
//这里就是根据自己的需求查出自己需要的数据,通过用户需要的商品字段标识查出表里相对应的英文标识。 
$skey[]= DB::select(&#39;字段标识&#39;)->from(&#39;字段表&#39;)->where(&#39;字段名称&#39;, &#39;=&#39;, $arrtitle[$p])->fetch_row(); 
$rows .= $skey[$p][&#39;字段标识&#39;].&#39;|&#39;; 
} 
if($rows){ $rows = rtrim($rows,&#39;|&#39;); } 
if(!empty($rows)){ $exrows = explode(&#39;|&#39;,$rows); }else{ $exrows = array(); } 
$skeys = array_merge($order,$exrows); 
$count1 = count($skeys); //字段的个数 
if(!empty($length)){ 
for($x=1;$x<$f;$x++){ //求出有多少件商品就的循环多少次 
$orders = array(); 
$orders[] = $act_tag; 
$orders[] = $channel_tag; 
$orders[] = time(); 
$newlen = array_merge($orders,$length[$x]); 
if($count1 !== count($newlen)){ //如果商品字段的长度和商品的长度不等就证明用户有哪个字段没录入 
$newrs = array(); 
echo "<script type=\"text/javascript\">alert(\"<font color=#f00;>".&#39;请检查第,&#39;.($x-1).&#39;件商品!&#39;.&#39;导入失败!&#39;."</font>"); </script>"; 
fclose($handle); 
exit(); 
}else{ //start 
$arrimport = array_combine($skeys,$newlen); //如果两个数组是相等的我就合并数组,并把导入csv里面的日期改为时间戳存储到数据库 
if(!empty($arrimport[&#39;start_time&#39;])){ $sta = strtotime($arrimport[&#39;start_time&#39;]); }else{ $sta=(int)0; } 
if(!empty($arrimport[&#39;end_time&#39;])){ $end = strtotime($arrimport[&#39;end_time&#39;]); }else{ $end=(int)0; } 
$arrtime=array(&#39;start_time&#39;=>$sta,&#39;end_time&#39;=>$end); 
if(!empty($arrimport[&#39;start_time&#39;]) && !empty($arrimport[&#39;end_time&#39;])){ 
$newrs=array_merge($arrimport,$arrtime); 
}else{ 
$newrs = array(); 
echo "<script type=\"text/javascript\">alert(\"<font color=#f00;>".&#39;请检查第,&#39;.($x-1).&#39;件商品!&#39;.&#39;导入失败!&#39;."</font>"); </script>"; 
fclose($handle); 
exit(); 
} 
if(count($skeys) == count($newrs)){ 
DB::insert(&#39;商品表&#39;, array_values($skeys)) 
->values(array_values($newrs)) 
->execute(); 
} 
} //end 
} 
} 
if($row-1==(int)0){ 
echo "<script type=\"text/javascript\">alert(\"<font color=#f00;>".&#39;您导入的商品为空!&#39;."</font>"); </script>"; 
}else{ 
echo "<script type=\"text/javascript\">alert(\"<font color=#f00;>".&#39;成功导入&#39;."<font color=#f00;>".($row-1)."</font>".&#39;件商品!&#39;."</font>"); 
} 
fclose($handle); 
} 
?>

上記は、私の仕事で必要な CSV インポート プロセスです。インポート方法とは異なる場合がありますが、いくつかのコードは常に役に立ちます。

以下は簡単なインポートです:

<form enctype="multipart/form-data" action="import.php" method="POST"> 
导入模板 
<label for="文件选择">文件选择:</label><input name="csv_goods" type="file" /> 
<input type="submit" value="导入" name="import" /> 
</form> 
<?php 
if (isset($_POST[&#39;import&#39;])){ 
$file = $_FILES[&#39;csv_goods&#39;]; 
$file_type = substr(strstr($file[&#39;name&#39;],&#39;.&#39;),1); 
// 检查文件格式 
if ($file_type != &#39;csv&#39;){ 
echo &#39;文件格式不对,请重新上传!&#39;; 
exit; 
} 
$handle = fopen($file[&#39;tmp_name&#39;],"r"); 
$file_encoding = mb_detect_encoding($handle); 
// 检查文件编码 
if ($file_encoding != &#39;ASCII&#39;){ 
echo &#39;文件编码错误,请重新上传!&#39;; 
exit; 
} 
$row = 0; 
while ($data = fgetcsv($handle,1000,&#39;,&#39;)){ 
//echo "<font color=red>$row</font>"; //可以知道总共有多少行 
$row++; 
if ($row == 1) 
continue; 
$num = count($data); 
// 这里会依次输出每行当中每个单元格的数据 
for ($i=0; $i<$num; $i++){ 
echo $data[$i]."<br>"; 
// 在这里对数据进行处理 
} 
} 
fclose($handle); 
} 
?>

上記はこの記事の全内容です。皆様の学習に役立つことを願っています。その他の関連コンテンツについては、こちらをご覧ください。 、PHP 中国語 Web サイトに注意してください。

関連する推奨事項:

PHP による中国語文字列インターセプト (mb_substr) の処理と中国語文字列の文字数の取得についての紹介

## PHP でカプセル化されたカールの呼び出しインターフェイスと共通関数の紹介

##

以上がCSVファイルをPHPにインポートする際に文字化けが発生する問題を解決する方法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。