phpで2つのcsvファイルを多次元配列にインポートし、array_diff関数を使用して違いを見つけて比較しようとしています。
私が使用している方法論は
1)予想されるcsvのすべてのレコードを取得し、arr1にダンプします
2)実際のcsvのすべてのレコードを取得し、arr2にダンプします
3)array_multisortを使用してarray1を並べ替えます
4)array_multisortを使用してarray2を並べ替えます
5)各レコードのarray_diff関数を使用して比較します(例:arr1[0][1]とarr2[0][1])
私の目的は、最小限の時間でphpスクリプトを使用してファイルを比較することです。上記のアプローチが最短であることがわかりました(最初にcsvコンテンツをMySQLにダンプし、dbクエリを使用して比較しようとしましたが、何らかの理由でクエリの動作が非常に遅いため、タイムアウト後にApacheサーバーがクラッシュします)
csvで最大300MBのサイズのファイルがありますが、通常は20列で10MBのサイズの70kレコードになります。
私が行ったことのコードを貼り付けています(上記の手順で)
$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は2013年1月12日、0.01は1行目です....2.csvは01/ 2013年12月と.01したがって、ハッシュが機能するとは思わない