php导入csv文件碰到乱码问题的解决方法


Posted in PHP onFebruary 10, 2014

今天主要是想写一个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); 
} 
?>
PHP 相关文章推荐
PHPShop存在多个安全漏洞
Oct 09 PHP
一个程序下载的管理程序(二)
Oct 09 PHP
PHP 编程请选择正确的文本编辑软件
Dec 21 PHP
PHP图片裁剪函数(保持图像不变形)
May 04 PHP
php按百分比生成缩略图的代码分享
May 10 PHP
推荐一款MAC OS X 下php集成开发环境mamp
Nov 08 PHP
实现PHP+Mysql无限分类的方法汇总
Mar 02 PHP
Zend Framework动作助手FlashMessenger用法详解
Mar 05 PHP
php关闭warning问题的解决方法
May 17 PHP
thinkPHP5框架导出Excel文件简单操作示例
Aug 03 PHP
ThinkPHP 5.x远程命令执行漏洞复现
Sep 23 PHP
PHP的图像处理实例小结【文字水印、图片水印、压缩图像等】
Dec 20 PHP
php判断正常访问和外部访问的示例
Feb 10 #PHP
php利用单例模式实现日志处理类库
Feb 10 #PHP
PHP遍历并打印指定目录下所有文件实例
Feb 10 #PHP
php生成excel文件的简单方法
Feb 08 #PHP
php中利用explode函数分割字符串到数组
Feb 08 #PHP
PHP判断变量是否为0的方法
Feb 08 #PHP
php读取文件内容的三种可行方法示例介绍
Feb 08 #PHP
You might like
PHP个人网站架设连环讲(一)
2006/10/09 PHP
php桌面中心(四) 数据显示
2007/03/11 PHP
用PHP的ob_start() 控制您的浏览器cache
2009/08/03 PHP
浅谈php中include文件变量作用域
2015/06/18 PHP
PHP入门教程之上传文件实例详解
2016/09/11 PHP
php实现多维数组排序的方法示例
2017/03/23 PHP
PHP使用第三方即时获取物流动态实例详解
2017/04/27 PHP
javascript 面向对象编程  function是方法(函数)
2009/09/17 Javascript
jQuery选中select控件 无法设置selected的解决方法
2010/09/01 Javascript
jQuery中append、insertBefore、after与insertAfter的简单用法与注意事项
2020/04/04 Javascript
JavaScript中的常见问题解决方法(乱码,IE缓存,代理)
2013/11/28 Javascript
jQuery根据元素值删除数组元素的方法
2015/06/24 Javascript
基于JavaScript代码实现微信扫一扫下载APP
2015/12/30 Javascript
jQueryeasyui 中如何使用datetimebox 取两个日期间相隔的天数
2017/06/13 jQuery
vue使用el-upload上传文件及Feign服务间传递文件的方法
2019/03/15 Javascript
如何正确理解vue中的key详解
2019/11/02 Javascript
vue分页插件的使用方法
2019/12/25 Javascript
小程序自动化测试的示例代码
2020/08/11 Javascript
PYTHON正则表达式 re模块使用说明
2011/05/19 Python
python实现博客文章爬虫示例
2014/02/26 Python
Python中列表(list)操作方法汇总
2014/08/18 Python
python协程之动态添加任务的方法
2019/02/19 Python
不到40行代码用Python实现一个简单的推荐系统
2019/05/10 Python
python实现证件照换底功能
2019/08/20 Python
基于Python爬取素材网站音频文件
2020/10/21 Python
美国珠宝精品店:Opulent Jewelers
2019/08/20 全球购物
ellesse美国官方商店:意大利高级运动服品牌
2019/10/29 全球购物
Douglas意大利官网:购买香水和化妆品
2020/05/27 全球购物
电子商务个人自荐信
2013/12/12 职场文书
运动会广播稿200字(10篇)
2014/10/12 职场文书
爱岗敬业事迹材料
2014/12/24 职场文书
员工离职感谢信
2015/01/22 职场文书
2015年学校信息技术工作总结
2015/05/25 职场文书
初中语文教学反思范文
2016/03/03 职场文书
高中班主任工作总结(范文)
2019/08/20 职场文书
Python基础详解之邮件处理
2021/04/28 Python