我试图通过将它们导入多维数组并使用 array_diff 函数找出差异来比较 php 中的 2 个 csv 文件。
我使用的方法是
1) 获取预期 csv 的每条记录并转储到 arr1
2) 获取实际 csv 的每条记录并转储到 arr2
3) 使用 array_multisort 对 array1 进行排序
4) 使用 array_multisort 对 array2 进行排序
5) 使用 array_diff 函数比较每条记录(例如 arr1[0][1] vs arr2[0][1])
我的目标是在尽可能短的时间内使用 php 脚本比较文件。我发现上述方法是最短的(最初尝试将 csv 内容转储到 MySQL 并使用 db 查询进行比较,但由于某些未知原因,查询工作速度非常慢,以至于超时后我的 Apache 服务器崩溃)
我在 csv 中有大小高达 300mb 的文件,但通常它是 70k 记录,有 20 列和 10mb 大小
我正在粘贴我所做的代码(按照上述步骤)
$header='';
$file_handle = fopen($fileExp, "r");
$k=0;
while ($data=fgetcsv($file_handle,0,$_POST['dl1'])) {
if(count($data)==1 && $data[0]=='')
continue;
else
{
$urarr1[$k]='';
for($i=0;$i<count($data);$i++)
{
if(in_array($i,$exclude_cols,true))
$rarr1[$k][$i]='NTBT';
else
$rarr1[$k][$i]=trim($data[$i]);
}
$k++;
}
}
fclose($file_handle);
echo '<br>Exp Record count: '.count($rarr1);
$header.='<br>Exp Record count: '.count($rarr1);
$hrow=$rarr1[0]; //fetch header row and then unset it
unset($rarr1[0]);
array_multisort($rarr1); //need to sort on all 20 columns asc
$rarr1=array_values($rarr1); //re-number the array
//writing the sorted o/p to file...debugging purposes
$fp = fopen($_POST['op'].'/file1.csv', 'w');
foreach ($rarr1 as $fields) {
fputcsv($fp, $fields);
}
fclose($fp);
//Repeat for actual .csv
$file_handle = fopen($fileAct, "r");
$k=0;
while ($data=fgetcsv($file_handle,0,$_POST['dl2'])) {
if(count($data)==1 && $data[0]=='')
continue;
else
{
for($i=0;$i<count($data);$i++)
{
if(in_array($i,$exclude_cols,true))
$rarr2[$k][$i]='NTBT';
else
$rarr2[$k][$i]=trim($data[$i]);
}
$k++;
}
}
fclose($file_handle);
unset($file_handle);
echo '<br>Act Record count: '.count($rarr2);
$header.='<br>Act Record count: '.count($rarr2);
unset($rarr2[0]);
array_multisort($rarr2);
$rarr2=array_values($rarr2);
$fp = fopen($_POST['op'].'/file2.csv', 'w');
foreach ($rarr2 as $fields) {
fputcsv($fp, $fields);
}
fclose($fp);
///Comparison logic
$header.= '<br>';
$header.= '<table>';
$header.= '<th>RECORD_ID</th>';
for($i=0;$i<count($hrow);$i++)
{
$header.= '<th>'.$hrow[$i].'_EXP</th>';
$header.= '<th>'.$hrow[$i].'_ACT</th>';
}
$r=array();
for($i=0;$i<count($rarr1);$i++)
{
if(array_diff($rarr1[$i],$rarr2[$i]) || array_diff($rarr2[$i],$rarr1[$i]))
{
$r[$i]=array_unique(array_merge(array_keys(array_diff($rarr1[$i],$rarr2[$i])),array_keys(array_diff($rarr2[$i],$rarr1[$i]))));
foreach($r[$i] as $key=>$v)
{
if(in_array($v,$calc_cols))
{
if(abs($rarr1[$i][$v]-$rarr2[$i][$v])<0.2)
{
unset($r[$i][$key]);
}
}
elseif(is_numeric($rarr1[$i][$v]) && is_numeric($rarr2[$i][$v]) && !in_array($v,$calc_cols) && ($rarr1[$i][$v]-$rarr2[$i][$v])==0)
{
unset($r[$i][$key]);
}
}
if(empty($r[$i]))
unset($r[$i]);
if(isset($r[$i]))
{
$header.= '<tr>';
$header.= '<td>'.$i.'</td>';
for($j=0;$j<count($rarr1[$i]);$j++)
{
if(in_array($j,$r[$i]))
{
$header.= '<td style="color:orange">'.$rarr1[$i][$j].'</td>';
$header.= '<td style="color:orange">'.$rarr2[$i][$j].'</td>';
}
else
{
$header.= '<td >'.$rarr1[$i][$j].'</td>';
$header.= '<td >'.$rarr2[$i][$j].'</td>';
}
}
$header.= '</tr>';
}
}
}
$header.= '</table>';
//print_r($r);
echo '<br>';
// if(!isset($r))
// $r[0]=0;
echo 'Differences :'.count($r) ;
$header.= '<br>';
$header.= 'Differences :'.count($r) ;
$time_end = microtime(true);
$execution_time = ($time_end - $time_start)/60; //dividing with 60 will give the execution time in minutes other wise seconds
echo '<br><b>Total Execution Time:</b> '.$execution_time.' Mins'; //execution time of the script
虽然最初我发现这适用于大多数文件,但后来我发现对于某些文件,由于未知原因,array_multisort 对 arr1 和 arr2 进行了不同的排序,即使内容看起来相同......我不确定这是因为数据类型不匹配,但我也尝试过类型转换,但它仍然以不同的方式排序但相同的数组
有人可以建议上面的代码可能有什么问题吗?另外,考虑到我上面提到的需求,有没有更方便的方式通过php来实现呢??也许是一个比较 .csv 文件之类的 php 插件?
编辑:按要求提供样本数据。只是一个快照,实际会有更多的列和行。如上所述,.csv 文件大小远远超过 10mb!文件 1 和文件 2
236|INPQR|31-AUG-12|200 |INR| 664|AAAAAA,PPPPP |0 |38972944.8 |0 |0 |38972944.8
236|INPQR|31-AUG-12|200 |INR| 6653|AAAAAA,PPPPP |0 |0 |0 |0 |0
236|INPQR|31-AUG-12|200 |USD| 6655|AAAAAA,PPPPP |0 |0 |0 |0 |0
236|INPQR|31-AUG-12|200 |USD| 664|AAAAAA,PPPPP |0 |63919609.97 |0 |0 |63919609.97
225|INPZQ|31-AUG-12|200 |USD| 6653|AAAAAA,PPPPP |0 |0 |0 |0 |0
225|INPZQ|31-AUG-12|200 |USD| 6655|AAAAAA,PPPPP |0 |0 |0 |0 |0
225|INPZQ|31-AUG-12|200 |USD| 6652|AAAAAA,PPPPP |0 |38972944.8 |0 |0 |38972944.8
225|INPZQ|31-AUG-12|200 |INR| 6652|AAAAAA,PPPPP |0 |63919609.97 |0 |0 |63919609.97
225|INPZQ|31-AUG-12|200 |INR| 6654|AAAAAA,PPPPP |0 |0 |0 |0 |0
225|INPZQ|31-AUG-12|200 |INR| 6654|AAAAAA,PPPPP
236|INPQR|31-AUG-12|200 |USD| 664|AAAAAA,PPPPP |0 |63919609.97 |0 |0 |63919609.97
225|INPZQ|31-AUG-12|200 |USD| 6653|AAAAAA,PPPPP |0 |0 |0 |0 |0
225|INPZQ|31-AUG-12|200 |USD| 6655|AAAAAA,PPPPP
236|INPQR|31-AUG-12|200 |INR| 664|AAAAAA,PPPPP |0 |38972944.8 |0 |0 |38972944.8
236|INPQT|31-AUG-12|200 |INR| 6653|AAAAAA,PPPPP |0 |0 |0 |0 |0
236|INPQR|31-AUG-12|200 |USD| 6655|AAAAAA,PPPPP |0 |0 |0 |0 |0
225|INPZQ|31-AUG-12|200 |USD| 6652|AAAAAA,PPPPP |0 |38972944.8 |0 |0 |38972944.8
225|INPZQ|31-AUG-12|200 |INR| 6652|AAAAAA,PPPPP |0 |63919609.97 |0 |0 |63919609.97
225|INPZQ|31-AUG-12|200 |USD| 6654|AAAAAA,PPPPP |0 |0 |0 |0 |0
225|INPZQ|31-AUG-12|200 |INR| 6654|AAAAAA,PPPPP
更新:2个csv文件可能包含不同的日期格式,每个文件可能代表不同格式的数字,例如 1.csv 可能有 12-jan-2013 和 0.01 作为第一行....2.csv 会有 01/ 12/2013 和 .01 因此我不认为哈希会起作用