如何使用PHP解析CSV文件
假设我有一个包含以下内容的如何使用PHP解析CSV文件,php,csv,fgetcsv,Php,Csv,Fgetcsv,假设我有一个包含以下内容的.csv文件: "text, with commas","another text",123,"text",5; "some without commas","another text",123,"text"; "some text with commas or no",,123,"text"; 如何通过PHP解析内容?只需使用函数解析CSV文件即可 $row=1; if($handle=fopen(“test.csv”、“r”)!==FALSE)
.csv
文件:
"text, with commas","another text",123,"text",5;
"some without commas","another text",123,"text";
"some text with commas or no",,123,"text";
如何通过PHP解析内容?只需使用函数解析CSV文件即可
$row=1;
if($handle=fopen(“test.csv”、“r”)!==FALSE){
while(($data=fgetcsv($handle,1000,“,”)!==FALSE){
$num=计数($data);
echo“$num字段位于第$row行:
\n”;
$row++;
对于($c=0;$c<$num;$c++){
echo$data[$c]。“
\n”;
}
}
fclose($handle);
}
我一直在寻找同样的东西,但没有使用一些不受支持的PHP类。Excel CSV并不总是使用引号分隔符,而是使用“”来转义引号,因为该算法可能是在80年代或其他时候提出的。在查看了PHP.NET评论部分中的几个.csv解析器之后,我看到了一些甚至使用回调或评估代码的解析器,它们要么无法正常工作,要么根本无法工作。因此,我为此编写了自己的例程,它们在最基本的PHP配置中工作。数组键可以是数字,也可以按标题行中给定的字段命名。希望这有帮助
function SW_ImplodeCSV(array $rows, $headerrow=true, $mode='EXCEL', $fmt='2D_FIELDNAME_ARRAY')
// SW_ImplodeCSV - returns 2D array as string of csv(MS Excel .CSV supported)
// AUTHOR: tgearin2@gmail.com
// RELEASED: 9/21/13 BETA
{ $r=1; $row=array(); $fields=array(); $csv="";
$escapes=array('\r', '\n', '\t', '\\', '\"'); //two byte escape codes
$escapes2=array("\r", "\n", "\t", "\\", "\""); //actual code
if($mode=='EXCEL')// escape code = ""
{ $delim=','; $enclos='"'; $rowbr="\r\n"; }
else //mode=STANDARD all fields enclosed
{ $delim=','; $enclos='"'; $rowbr="\r\n"; }
$csv=""; $i=-1; $i2=0; $imax=count($rows);
while( $i < $imax )
{
// get field names
if($i == -1)
{ $row=$rows[0];
if($fmt=='2D_FIELDNAME_ARRAY')
{ $i2=0; $i2max=count($row);
while( list($k, $v) = each($row) )
{ $fields[$i2]=$k;
$i2++;
}
}
else //if($fmt='2D_NUMBERED_ARRAY')
{ $i2=0; $i2max=(count($rows[0]));
while($i2<$i2max)
{ $fields[$i2]=$i2;
$i2++;
}
}
if($headerrow==true) { $row=$fields; }
else { $i=0; $row=$rows[0];}
}
else
{ $row=$rows[$i];
}
$i2=0; $i2max=count($row);
while($i2 < $i2max)// numeric loop (order really matters here)
//while( list($k, $v) = each($row) )
{ if($i2 != 0) $csv=$csv.$delim;
$v=$row[$fields[$i2]];
if($mode=='EXCEL') //EXCEL 2quote escapes
{ $newv = '"'.(str_replace('"', '""', $v)).'"'; }
else //STANDARD
{ $newv = '"'.(str_replace($escapes2, $escapes, $v)).'"'; }
$csv=$csv.$newv;
$i2++;
}
$csv=$csv."\r\n";
$i++;
}
return $csv;
}
function SW_ExplodeCSV($csv, $headerrow=true, $mode='EXCEL', $fmt='2D_FIELDNAME_ARRAY')
{ // SW_ExplodeCSV - parses CSV into 2D array(MS Excel .CSV supported)
// AUTHOR: tgearin2@gmail.com
// RELEASED: 9/21/13 BETA
//SWMessage("SW_ExplodeCSV() - CALLED HERE -");
$rows=array(); $row=array(); $fields=array();// rows = array of arrays
//escape code = '\'
$escapes=array('\r', '\n', '\t', '\\', '\"'); //two byte escape codes
$escapes2=array("\r", "\n", "\t", "\\", "\""); //actual code
if($mode=='EXCEL')
{// escape code = ""
$delim=','; $enclos='"'; $esc_enclos='""'; $rowbr="\r\n";
}
else //mode=STANDARD
{// all fields enclosed
$delim=','; $enclos='"'; $rowbr="\r\n";
}
$indxf=0; $indxl=0; $encindxf=0; $encindxl=0; $enc=0; $enc1=0; $enc2=0; $brk1=0; $rowindxf=0; $rowindxl=0; $encflg=0;
$rowcnt=0; $colcnt=0; $rowflg=0; $colflg=0; $cell="";
$headerflg=0; $quotedflg=0;
$i=0; $i2=0; $imax=strlen($csv);
while($indxf < $imax)
{
//find first *possible* cell delimiters
$indxl=strpos($csv, $delim, $indxf); if($indxl===false) { $indxl=$imax; }
$encindxf=strpos($csv, $enclos, $indxf); if($encindxf===false) { $encindxf=$imax; }//first open quote
$rowindxl=strpos($csv, $rowbr, $indxf); if($rowindxl===false) { $rowindxl=$imax; }
if(($encindxf>$indxl)||($encindxf>$rowindxl))
{ $quoteflg=0; $encindxf=$imax; $encindxl=$imax;
if($rowindxl<$indxl) { $indxl=$rowindxl; $rowflg=1; }
}
else
{ //find cell enclosure area (and real cell delimiter)
$quoteflg=1;
$enc=$encindxf;
while($enc<$indxl) //$enc = next open quote
{// loop till unquoted delim. is found
$enc=strpos($csv, $enclos, $enc+1); if($enc===false) { $enc=$imax; }//close quote
$encindxl=$enc; //last close quote
$indxl=strpos($csv, $delim, $enc+1); if($indxl===false) { $indxl=$imax; }//last delim.
$enc=strpos($csv, $enclos, $enc+1); if($enc===false) { $enc=$imax; }//open quote
if(($indxl==$imax)||($enc==$imax)) break;
}
$rowindxl=strpos($csv, $rowbr, $enc+1); if($rowindxl===false) { $rowindxl=$imax; }
if($rowindxl<$indxl) { $indxl=$rowindxl; $rowflg=1; }
}
if($quoteflg==0)
{ //no enclosured content - take as is
$colflg=1;
//get cell
// $cell=substr($csv, $indxf, ($indxl-$indxf)-1);
$cell=substr($csv, $indxf, ($indxl-$indxf));
}
else// if($rowindxl > $encindxf)
{ // cell enclosed
$colflg=1;
//get cell - decode cell content
$cell=substr($csv, $encindxf+1, ($encindxl-$encindxf)-1);
if($mode=='EXCEL') //remove EXCEL 2quote escapes
{ $cell=str_replace($esc_enclos, $enclos, $cell);
}
else //remove STANDARD esc. sceme
{ $cell=str_replace($escapes, $escapes2, $cell);
}
}
if($colflg)
{// read cell into array
if( ($fmt=='2D_FIELDNAME_ARRAY') && ($headerflg==1) )
{ $row[$fields[$colcnt]]=$cell; }
else if(($fmt=='2D_NUMBERED_ARRAY')||($headerflg==0))
{ $row[$colcnt]=$cell; } //$rows[$rowcnt][$colcnt] = $cell;
$colcnt++; $colflg=0; $cell="";
$indxf=$indxl+1;//strlen($delim);
}
if($rowflg)
{// read row into big array
if(($headerrow) && ($headerflg==0))
{ $fields=$row;
$row=array();
$headerflg=1;
}
else
{ $rows[$rowcnt]=$row;
$row=array();
$rowcnt++;
}
$colcnt=0; $rowflg=0; $cell="";
$rowindxf=$rowindxl+2;//strlen($rowbr);
$indxf=$rowindxf;
}
$i++;
//SWMessage("SW_ExplodeCSV() - colcnt = ".$colcnt." rowcnt = ".$rowcnt." indxf = ".$indxf." indxl = ".$indxl." rowindxf = ".$rowindxf);
//if($i>20) break;
}
return $rows;
}
函数SW\u introdecsv(数组$rows,$headerrow=true,$mode='EXCEL',$fmt='2D\u FIELDNAME\u array')
//SW_内爆csv-以csv字符串形式返回2D数组(支持MS Excel.csv)
//作者:tgearin2@gmail.com
//发布日期:2013年9月21日测试版
{$r=1;$row=array();$fields=array();$csv=”“;
$escapes=array('\r'、'\n'、'\t'、'\\'、'\');//两字节转义码
$escapes2=数组(“\r”、“\n”、“\t”、“\\”、“\\”);//实际代码
如果($mode=='EXCEL')//escape code=“”
{$delim=',';$enclose='”;$rowbr=“\r\n”;}
else//mode=标准所有封闭字段
{$delim=',';$enclose='”;$rowbr=“\r\n”;}
$csv=“”;$i=-1;$i2=0;$imax=count($rows);
而($i<$imax)
{
//获取字段名
如果($i==-1)
{$row=$rows[0];
如果($fmt=='2D\u字段名\u数组')
{$i2=0;$i2max=count($row);
while(列表($k,$v)=每个($row))
{$fields[$i2]=$k;
$i2++;
}
}
else//if($fmt='2D\u编号\u数组')
{$i2=0;$i2max=(count($rows[0]);
而($i2的答案要短一点,因为:
我喜欢这个
$data = str_getcsv($CsvString, "\n"); //parse the rows
foreach ($data as &$row) {
$row = str_getcsv($row, "; or , or whatever you want"); //parse the items in rows
$this->debug($row);
}
在我的例子中,我将通过web服务获取csv,因此通过这种方式,我不需要创建文件。但是,如果需要使用文件进行解析,只需要将csv文件作为字符串传递到数组中即可
$csv = array_map('str_getcsv', file('data.csv'));
刚刚发现了一种在解析时获取索引的简便方法。我的脑子被炸了
$handle = fopen("test.csv", "r");
for ($i = 0; $row = fgetcsv($handle ); ++$i) {
// Do something will $row array
}
fclose($handle);
来源:你基本上是在问,是否有比股票全局函数方法更好的面向对象方法来处理w/CSV解析。我要说的是重写这个问题,因为这听起来不像是解析CSV的问题。@quickshiftin很抱歉,没关系,我只是说……如果你想要一个类就可以了(我在工作中对它做了一些调整…)需要注意的是,该函数不能正确处理CSV中的引号。特别是,它不能处理wikipedia中的示例:有一个开放的bug,但它已被关闭为“不会修复”。请注意,如果实际值中有任何换行符(而不是每个CSV行末尾的行分隔符),则该函数不起作用,因为file
函数在换行符上拆分,并且不知道CSV用于包含字段值的引号。如何使用不同的分隔符?(;而不是,)使用以下方法解决换行问题:数组映射('str_getcsv',file('data.CSV',file_IGNORE_new_line | file_SKIP_EMPTY_line));你知道,给各自的作者评分是很好的:@Maxim Kovalevsky,如何跳过标题或第一行请注意,如果实际值中有任何换行符(而不是每行末尾的行分隔符),则这不起作用,因为文件
函数在换行符上拆分,并且不知道CSV用于包含字段值的引号。@JordanLev那么您推荐什么?@Julix use。如果您知道导入的数据在单个值中永远不会有换行符,那么这个较短的版本很好,但其他更健壮的解决方案是值得的额外的代码行。我在保存到CSV之前进行了编码,并在阅读时进行解码——这确保了没有断行,对吗?——或者它完全丢失了它们(URL编码中会有断行吗?)这个答案非常适用于新行,并使用了php文件函数的魔力。ThanksOur服务器有PHP5.2.9,我无法访问str_getcsv,因为这个原因。另一方面,fgetcsv的日期一直到PHP4,所以这很有帮助。谢谢。只是想知道为什么使用for循环而不是while循环?@valerie我几乎总是需要一个in循环解析CSV时使用dex。for循环提供的索引没有单独的声明和递增符。这对我来说不正常。例如,这:aaa,bbb,“ccc\nddd”,eee
被解析为两行(而不是所需的一行),而不是一行。似乎“
出现在字段内部时(而不是在其开始或结束时)不会被识别为存储模块。因此,$data=str\u getcsv(..)
可以替换为$data=explode(..)
,我猜这更有效,更能传达意图。。。
$csv = array_map('str_getcsv', file('data.csv'));
$handle = fopen("test.csv", "r");
for ($i = 0; $row = fgetcsv($handle ); ++$i) {
// Do something will $row array
}
fclose($handle);