Heim  >  Artikel  >  Backend-Entwicklung  >  So lösen Sie das Problem verstümmelter Zeichen beim Importieren von CSV-Dateien in PHP

So lösen Sie das Problem verstümmelter Zeichen beim Importieren von CSV-Dateien in PHP

不言
不言Original
2018-07-03 16:15:082730Durchsuche

In diesem Artikel wird hauptsächlich die Lösung für das Problem verstümmelter Zeichen beim Importieren von CSV-Dateien in PHP vorgestellt. Freunde, die es benötigen, können darauf zurückgreifen.

Heute möchte ich hauptsächlich eine Methode zum Importieren von CSV-Dateien in PHP schreiben Tatsächlich habe ich viel online danach gesucht. Alle lassen sich wie beim Import umsetzen. Beim Importieren sind jedoch zwei Probleme aufgetreten. Zum einen hatte der Test beim Schreiben von Code unter Windows verstümmelte Zeichen, die dann behoben wurden. Der zweite Grund ist, dass bei der Übermittlung an das Linux-System erneut verstümmelte Zeichen auftraten. Ich kannte den Grund für den verstümmelten Code zunächst nicht. Am Ende stellte ich in einer meiner Gruppen eine Frage. Er sagte, dass er bei der Übermittlung an Linux auf einen Fehler gestoßen sei. Später stellte sich heraus, dass die Ursache verstümmelte Zeichen waren. Kommen wir gleich zur Sache und sehen, wie wir diese beiden Probleme lösen können!

Das Problem ist gelöst:

PHP liest die CSV-Datei, und die chinesische Datei kann unter Windows nicht gelesen werden. Ich dachte sofort an eine Funktion mb_convert_encoding(); nehmen Sie die folgenden Einstellungen vor: $str = mb_convert_encoding ($str, „UTF-8“, „GBK“); Natürlich können Sie auch iconv(); verwenden, um iconv('GBK', "UTF-8//TRANSLIT//IGNORE", $str); wie folgt zu lösen: .

Lösung für Problem zwei:

PHP liest CSV-Dateien, aber Chinesisch kann unter Linux nicht gelesen werden. Ich habe die Lösung nach Baidu und Google gefunden.

Ich habe sie gerade hinzugefügt des Codes setlocale(LC_ALL, 'zh_CN'); Ja, es wird deine Augen blenden. So einfach ist das, und wenn Sie es nicht wüssten, könnten Sie viel Zeit damit verbringen, es herauszufinden.

PHP setlocale()-Funktionserklärung

Definition und Verwendung

setlocale()-Funktion legt regionale Informationen (regionale Informationen) fest.

Regionale Informationen sind Sprache, Währung, Zeit und andere Informationen für ein geografisches Gebiet. Diese Funktion gibt das aktuelle Gebietsschema oder bei einem Fehler „false“ zurück.

Die folgenden sind häufig verwendete Regionskennungen zum Sammeln von Daten:

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

Zum Beispiel
utf-8: setlocale(LC_ALL, 'en_US.UTF-8′);
Vereinfachtes Chinesisch: setlocale(LC_ALL, 'zh_CN');

Der Grund, warum ich Ihnen von der Funktion setlocale() erzähle, ist, dass beim Importieren der CSV-Datei in das Linux-System verstümmelte Zeichen aufgetreten sind. einschließlich der Verwendung der Funktionen mb_convert_encoding() und iconv() konnte das endgültige Problem nicht gelöst werden. Schließlich habe ich zu Beginn des Imports der CSV-Datei diesen Satz setlocale(LC_ALL, 'zh_CN'); eingefügt und es war einfach. Dann habe ich nach Informationen gesucht und festgestellt, dass die Funktion fgetcsv() empfindlich ist Gebietsschemaeinstellungen. Wenn LANG beispielsweise auf en_US.UTF-8 eingestellt ist, weisen Einzelbyte-codierte Dateien Lesefehler auf, daher müssen wir die Kultur festlegen. Speziell mit allen geteilt.

Ich habe auch den folgenden Code ausprobiert, konnte ihn aber nicht zum Laufen bringen. Dies sind die Header-Einstellungen zum Generieren von CSV-Dateien. Bei mir funktioniert es vielleicht nicht, bei Ihnen aber vielleicht. Also habe ich es geklärt und mein Bestes gegeben, um Kollegen zu helfen, die beim Importieren von CSV-Dateien auf verstümmelte Zeichen gestoßen sind, weil es wirklich schwierig war, damit umzugehen, wenn es keine andere Möglichkeit gab. Jeder kann es ausprobieren! Es gibt immer einen, der dir gehört.

<?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; 
?>

Sehen wir uns den Code für PHP zum Importieren von CSV-Dateien genauer an:

Eine kurze Einführung in die beiden Funktionen,

Die von erkannte Zeichenkodierung mb_detect_encoding() oder gibt FALSE zurück, wenn die Codierung der angegebenen Zeichenfolge nicht erkannt werden kann.

Die Funktion fgetcsv() liest eine Zeile aus dem Dateizeiger und analysiert das CSV-Feld. Ähnlich wie fgets(), außer dass fgetcsv() die gelesene Zeile analysiert, die Felder im CSV-Format findet und dann ein Array zurückgibt, das diese Felder enthält. fgetcsv() gibt bei einem Fehler FALSE zurück, auch wenn das Ende der Datei erreicht wird.

Hinweis: Ab PHP 4.3.5 ist die Operation von fgetcsv() binärsicher.

Hinweis: Leere Zeilen in der CSV-Datei werden als Array mit einem einzelnen Nullfeld zurückgegeben und nicht als Fehler behandelt.

Hinweis: Diese Funktion reagiert empfindlich auf die Gebietsschemaeinstellungen. Wenn LANG beispielsweise auf en_US.UTF-8 eingestellt ist, weisen Einzelbyte-codierte Dateien Lesefehler auf.

Hinweis: Wenn Sie feststellen, dass PHP beim Lesen von Dateien die Zeilenendzeichen von Macintosh-Dateien nicht erkennen kann, können Sie die Laufzeitkonfigurationsoption auto_detect_line_endings aktivieren.

<?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); 
} 
?>

Das Obige ist der CSV-Importvorgang, den ich für meine Arbeit durchführen muss. Er kann sich von Ihrer Importmethode unterscheiden, aber einige Codes werden Ihnen immer hilfreich sein!

Das Folgende ist ein einfacher Import:

<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); 
} 
?>

Das Obige ist der gesamte Inhalt dieses Artikels. Ich hoffe, dass er für alle zum Lernen hilfreich ist Bitte achten Sie auf die chinesische PHP-Website!

Verwandte Empfehlungen:

Einführung in die PHP-Verarbeitung des Abfangens chinesischer Zeichenfolgen (mb_substr) und das Ermitteln der Anzahl der Zeichen in chinesischen Zeichenfolgen

Einführung in die PHP-gekapselte Curl-Aufrufschnittstelle und allgemeine Funktionen

Das obige ist der detaillierte Inhalt vonSo lösen Sie das Problem verstümmelter Zeichen beim Importieren von CSV-Dateien in PHP. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn