>  기사  >  백엔드 개발  >  csv 파일을 PHP로 가져올 때 문자가 깨지는 문제를 해결하는 방법

csv 파일을 PHP로 가져올 때 문자가 깨지는 문제를 해결하는 방법

不言
不言원래의
2018-07-03 16:15:082806검색

이 글은 주로 PHP에서 CSV 파일을 가져올 때 문자가 깨지는 문제에 대한 해결책을 소개합니다. 필요한 친구들은 참고하면 됩니다.

오늘은 주로 PHP에서 CSV 파일을 가져오는 방법을 작성하고 싶습니다. 온라인 검색이 많다. 가져오는 방법을 모두 구현할 수 있습니다. 하지만 가져올 때 두 가지 문제가 발생했습니다. 하나는 Windows에서 코드를 작성할 때 테스트에서 문자가 깨져서 해결되었다는 것입니다. 두 번째는 리눅스 시스템에 제출했을 때 문자 깨짐 현상이 다시 발생했다는 것입니다. 처음에는 코드가 왜곡되는 이유를 몰랐습니다. 처음에는 코드 svn 제출에 오류가 있는 줄 알았습니다. 결국 내 그룹 중 하나에 질문을 했습니다. Windows에서 svn 제출 시 오류가 발생했다고 하더군요. Linux에 제출할 때 처음에는 항상 오류가 발생했는데 나중에는 문자가 깨져서 발생하는 것으로 밝혀졌습니다. 본론으로 들어가 이 두 가지 문제를 해결하는 방법을 살펴보겠습니다!

문제가 해결되었습니다:

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 이후에 해결책을 찾았습니다.

코드 한 줄을 추가하는 것입니다. 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');이라는 문장을 추가했는데 쉽게 완료되었습니다. 그런 다음 정보를 검색해 보니 fgetcsv() 함수가 로케일 설정. 예를 들어 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; 
?>

PHP가 csv 파일을 가져오는 코드를 자세히 살펴보겠습니다.

두 함수에 대한 간략한 소개,

mb_Detect_encoding()은 문자 인코딩이 감지되거나 지정된 문자열의 인코딩이 감지되면 FALSE를 반환합니다. 감지할 수 없습니다.

fgetcsv() 함수는 파일 포인터에서 한 줄을 읽고 CSV 필드를 구문 분석합니다. fgetcsv()가 읽기 행을 구문 분석하고 CSV 형식의 필드를 찾은 다음 해당 필드가 포함된 배열을 반환한다는 점을 제외하면 fgets()와 유사합니다. 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 중국어 웹사이트를 주목하세요!

관련 권장 사항:

PHP 처리 중국어 문자열 가로채기(mb_substr) 및 중국어 문자열의 문자 수 가져오기 소개

PHP 캡슐화 컬 호출 인터페이스 및 일반 함수 소개

위 내용은 csv 파일을 PHP로 가져올 때 문자가 깨지는 문제를 해결하는 방법의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.