如何解決php匯入csv檔案碰到亂碼的問題

來源:互聯網
上載者:User
這篇文章主要介紹了php匯入csv檔案碰到亂碼問題的解決方案,需要的朋友可以參考下

今天主要是想寫一個php匯入csv檔案的方法,其實網上一搜一大把。都是可以實現怎麼去匯入的。但是我匯入的時候遇到了兩個問題,一個是在windows上寫代碼的時候測試發生了亂碼問題,然後解決了。第二個是提交到linux系統上的時候又發生了亂碼。我開始還不清楚是亂碼的原因,一開始我還以為是代碼svn提交發生的錯誤,到最後我在我的一個群裡提問了一下,一朋友是做phpcms的,他說他遇到從Windows提交到Linux的時候剛開始也總是發生錯誤,後來排查原因就是亂碼導致成的。下面切入正題看怎麼解決兩個問題的吧!

問題一解決:

php讀取csv檔案,在windows上出現中文讀取不到的情況,本人立馬想到一個函數mb_convert_encoding();作如下設定 $str = mb_convert_encoding($str, "UTF-8", "GBK");然後就可以了。當然你也可以用iconv();作如下設定iconv(‘GBK',”UTF-8//TRANSLIT//IGNORE”,$str);這兩個函數來解決在windows上面發生亂碼的問題。

問題二解決:

php讀取csv檔案,在linux上出現中文讀取不到的情況,百度,google後找到解決辦法

就是添加了一行代碼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()兩個函數都是沒搞定最後問題的。最後就加了這一句setlocale(LC_ALL, ‘zh_CN');加在匯入csv檔案開始的代碼前面就輕鬆搞定了,然後我又找了一下資料,發現fgetcsv()函數對地區設定是敏感的。比如說 LANG 設為 en_US.UTF-8 的話,單位元組編碼的檔案就會出現讀取錯誤,所以我們需要對其進列區域性的設定。特分享給大家。

我還嘗試用了以下代碼也沒能搞定,這些都是產生csv檔案的header的設定。可能在我這裡不起作用,但是在你那裡也說不定哦。所以我都整理出來,儘可能的協助遇到匯入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; ?>

下面就再來具體看看php匯入csv檔案的代碼:

兩個函數簡單介紹一下,

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, 'zh_CN'); //設定地區資訊(地區資訊) $file = $_FILES['files']; $file_type = substr(strstr($file['name'],'.'),1); if ($file_type != 'csv'){ echo "<script type=\"text/javascript\">alert(\"檔案格式錯誤,請重新上傳!\"); </script>"; exit; } $handle = fopen($file['tmp_name'],"r"); $file_encoding = mb_detect_encoding($handle); if ($file_encoding != 'ASCII'){ echo "<script type=\"text/javascript\">alert(\"檔案編碼錯誤,請重新上傳!\"); </script>"; exit; } $row = 0; $str=""; $sy=""; while ($data = fgetcsv($handle,1000,',')){ $row++; if ($row == 0) continue; $num = count($data); for ($i=0; $i<$num; $i++){ $str = (string)$data[$i].'|'; $str = mb_convert_encoding($str, "UTF-8", "GBK"); //已知源碼為GBK,轉換為utf-8 $sy .= $str; //我這裡做的比較複雜,是用'|'將csv檔案裡面的內容用'|'全部拼起來,因為我匯入的是商品資訊,需要根據使用者需 //要匯入的資料去定義哪些資料是需要匯入的。 } } if ($sy) { $sy = rtrim($sy, '|'); } $arr = explode('|',$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('欄位標識', '欄位名稱')->from('欄位表')->fetch_all(); foreach ($arrtagname as $value) { $arrfileds[$value['fileds_tags']] = $value['fileds_name']; } foreach ($fileds as $v) { $temarr= explode('-', $v); if (isset($temarr[0]) && !empty($temarr[0])) { if (isset($temarr[1]) && !empty($temarr[1])) { if ($temarr[1] == 'wenben') { $arrtitle[] = $arrfileds[$temarr[0]].'文本'; } } else { if ($temarr[0] != 'pic') { //是取出欄位是圖片就給去掉 $arrtitle[] = $arrfileds[$temarr[0]]; } } } } $skey = array(); $order = array(); $order[] = 'act_tag'; $order[] = 'channel_tag'; $order[] = 'created_time'; $order[] = 'orderby'; $rows =''; $f = $co/$num;//求出有多少件商品 for($p=0;$p<count($arrtitle);$p++){ //這裡就是根據自己的需求查出自己需要的資料,通過使用者需要的商品欄位標識查出表裡相對應的英文標識。 $skey[]= DB::select('欄位標識')->from('欄位表')->where('欄位名稱', '=', $arrtitle[$p])->fetch_row(); $rows .= $skey[$p]['欄位標識'].'|'; } if($rows){ $rows = rtrim($rows,'|'); } if(!empty($rows)){ $exrows = explode('|',$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;>".'請檢查第,'.($x-1).'件商品!'.'匯入失敗!'."</font>"); </script>"; fclose($handle); exit(); }else{ //start $arrimport = array_combine($skeys,$newlen); //如果兩個數組是相等的我就合并數組,並把匯入csv裡面的日期改為時間戳記儲存到資料庫 if(!empty($arrimport['start_time'])){ $sta = strtotime($arrimport['start_time']); }else{ $sta=(int)0; } if(!empty($arrimport['end_time'])){ $end = strtotime($arrimport['end_time']); }else{ $end=(int)0; } $arrtime=array('start_time'=>$sta,'end_time'=>$end); if(!empty($arrimport['start_time']) && !empty($arrimport['end_time'])){ $newrs=array_merge($arrimport,$arrtime); }else{ $newrs = array(); echo "<script type=\"text/javascript\">alert(\"<font color=#f00;>".'請檢查第,'.($x-1).'件商品!'.'匯入失敗!'."</font>"); </script>"; fclose($handle); exit(); } if(count($skeys) == count($newrs)){ DB::insert('商品表', array_values($skeys)) ->values(array_values($newrs)) ->execute(); } } //end } } if($row-1==(int)0){ echo "<script type=\"text/javascript\">alert(\"<font color=#f00;>".'您匯入的商品為空白!'."</font>"); </script>"; }else{ echo "<script type=\"text/javascript\">alert(\"<font color=#f00;>".'成功匯入'."<font color=#f00;>".($row-1)."</font>".'件商品!'."</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['import'])){ $file = $_FILES['csv_goods']; $file_type = substr(strstr($file['name'],'.'),1); // 檢查檔案格式 if ($file_type != 'csv'){ echo '檔案格式不對,請重新上傳!'; exit; } $handle = fopen($file['tmp_name'],"r"); $file_encoding = mb_detect_encoding($handle); // 檢查檔案編碼 if ($file_encoding != 'ASCII'){ echo '檔案編碼錯誤,請重新上傳!'; exit; } $row = 0; while ($data = fgetcsv($handle,1000,',')){ //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); } ?>

以上就是本文的全部內容,希望對大家的學習有所協助,更多相關內容請關注topic.alibabacloud.com!

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.