PHP - Display differences between two CSV files - php

I have written a small script which upload two csv files and compare them.
//set files upload directory
$target_dir1 = "uploads/old/";
$target_file1 = $target_dir1 . basename($_FILES["fileToUpload1"]["name"]);
$target_dir2 = "uploads/new/";
$target_file2 = $target_dir2 . basename($_FILES["fileToUpload2"]["name"]);
$uploadOk = 1;
//Upload files
if ($uploadOk == 0) {
echo "<BR> Sorry, your files were not uploaded. <BR>";
} else {
if (move_uploaded_file($_FILES["fileToUpload1"]["tmp_name"], $target_file1)) {
echo "<BR> The 1st file ". basename( $_FILES["fileToUpload1"]["name"]). " has been uploaded. <BR>";
} else {
echo "<BR> Sorry, there was an error uploading your 1st file. <BR>";
}
if (move_uploaded_file($_FILES["fileToUpload2"]["tmp_name"], $target_file2)) {
echo "<BR> The 2nd file ". basename( $_FILES["fileToUpload2"]["name"]). " has been uploaded.<BR>";
} else {
echo "<BR> Sorry, there was an error uploading your 2nd file. <BR>";
}
}
//Get contetnt 1st file
$table1 = Array();
$filehandle1 = fopen($target_file1, "r") ;
if($filehandle1 !== FALSE) {
while(! feof($filehandle1)) { // feof end of file
$data1 = fgetcsv($filehandle1, 1000, ",");
array_push($table1, $data1);
}
}
fclose($filehandle1);
//Get content 2nd file
$table2 = Array();
$filehandle2 = fopen($target_file2, "r") ;
if($filehandle2 !== FALSE) {
while(! feof($filehandle2)) {
$data2 = fgetcsv($filehandle2, 1000, ",");
array_push($table2, $data2);
}
}
fclose($filehandle2);
//Find difference between these two files
$headers= array();
$headers = $table1[0];
$i= 0;
foreach ($table1 as $table) {
echo '<BR>';
$diff = array_diff($table2[$i], $table);
if(!empty($diff)) {
print_r($diff);
$chiave= key($diff);
echo $headers[$chiave];
};
echo '<BR>';
$i++;
}
And this is the error I get, however difference between the two files are dispalyed correctly:
Warning: array_diff(): Argument #1 is not an array in /var/www/csv_files/upload.php on line 67 Call Stack: 0.0053 337384 1. {main}() /var/www/csv_files/upload.php:0 0.0064 367220 2. array_diff() /var/www/csv_files/upload.php:67

You get this error because the first argument is not a array where one is expected. You are now checking a table with the nth element of a array but not the whole array. I think you are making a mistake in thinking table2 is a 2 dimensional array, and it's not. It is used a one dimensional array with nth data2 elements.
Hope this helps!

Seems yes, sometimes table2 is empty or those CSV files have different amount of rows - as result that warning.
So - you need add extra checks if $table2[$i] is not null.
Just a bit another variant from me - how to read file faster (Get content 1st and second file):
$table1 = file($target_file1);
$table2 = file($target_file2);
And then you can do same things as before, with extra tests:
if (count($table1)) {
$headers = str_getcsv($table1[0]);
foreach ($table1 as $key => $table) {
if (!isset($table2[$key])) {
echo 'Row ' . ($key+1) . ' is not exists in second CSV file.';
} else {
$diff = array_diff(str_getcsv($table2[$key]), str_getcsv($table));
// Here is code as in your example
print_r($diff);
$chiave = key($diff);
echo $headers[$chiave];
}
}
}
Good luck! :)

Related

Php: Delete string from text file [duplicate]

This question already has answers here:
How to delete a line from the file with php?
(10 answers)
Closed last year.
I need to delete a specific string set from a txt file. Currently, the code works in a similar manner to post the data directly to the file. However, trying to remove the same data, inputted in the same manner, will not allow it. In it's current state, the code looks like this for the string removal.
We were NOT allowed to use prebuilt sorting functions or use functions like str_replace or similar code.
Here is the current code for the string removal:
$blankReplace = "";
$found = false;
$fileData = file($fileInput,FILE_IGNORE_NEW_LINES);
for($i = 0; ($i < count($fileData)) && != $found; $i ++)
{
if($fullNameAndEmail == $fileData[$i])
{
$pos = $i;
$name = $fileData[$i];
$found = true;
}
}
if($found == true)
{
// Exit path. Go to for($j = 0) path
unset($fileData[$pos]);
shuffle($fileData);
}
else
{
//Error Msg
}
$writeToFile = fopen($inputFile,'w+');
for($j = 0;$j<count($fileData);$j++)
{
if(trim($fileData[$j]) != " ")
{
$rewrittenList = trim($fileData[$j])."\n";
fwrite($writeToFile, $rewrittenList);
}
}
The code outputs an error of T_IS_NOT_EQUAL in code upon researching the error. The data comes in as direct data from the file() read, so it should work. The error is pointing at for($i = 0; ($i < count($fileData)) && != $found; $i ++) line currently, but likely also references a similar occurrence in the code.
The data is inputted in the format:
firstname lastname emailaddress
I also need to be able to handle if multiple instances of the mentioned name occur so say we have:
Matt Person emailaddr#email.com
Matt Person emailaddr#email.com
That it will delete one instance, and not all, in cases similar to this.
Any help is appreciated, Thank you for your time in advance.
EDIT:
Example input:
Matthew person person#email.com
John holton person#email.com
Person Name person#gmail.com
The user will input a person's name (in format above) and it will result in removing a person. Say they input into the form:
$fullName = "Matthew person";
$emailAddr = "person#email.com";
The output will edit the data to put the data into a single line again
$fullNameAndEmail = $firstName." ".$lastName." ".$emailAddr;
The output of the code, in this example will remove "Matthew person person#email.com"
So the output in the text file will output:
John holton person#email.com
Person Name person#gmail.com
Edit 2: Code in it's current state
<!doctype HTML>
<html>
<meta charset="utf-8">
<head>
<title>Updating the guest book!</title>
</head>
<body>
<?php
$fileInput = "guestBook.txt";
$fileInputInData = file_get_contents($fileInput); // Gets data from file
$testBool = file_exists($fileInput);
$fullName = trim($_POST["fullName"]);
$emailAddr = trim($_POST["emailAddr"]);
$fileSize = filesize($fileInput);
if(!empty($fullName) and !empty($emailAddr))
{
if($testBool == 0)
{
echo "There was an issue with the file. Please have it checked.</br>";
}
else
{
echo "Made it into else path for testBool </br>";
if($fileSize > 0)
{ #code for truth
echo "Made it into filesize check. Filesize: $fileSize </br>";
$fullNameLen = strlen($fullName);
$emailAddrLen = strlen($emailAddr);
$fullNameArr = explode(" ", $fullName);
$firstName = trim($fullNameArr[0]);
$lastName = trim($fullNameArr[1]);
$fullNameToWrite =$firstName." ".$lastName;
$emailAddrCheck=substr_count($emailAddr, "#");
if ($emailAddrCheck == 1)
{
echo "Email address check passed</br>";
#email addr entered right path
$fullNameAndEmail =$fullNameToWrite." ".$emailAddr." has signed in.\n";
$inputFile = "guestBook.txt";
//$pos = strpos($writeToFile, $fullNameAndEmail);
//$writeToFileEx = explode("\n", $fileInputInData);
$blankReplace = "";
$str = $fileInputInData;
$find = $fullNameAndEmail;
$arr=explode("\n", $str);
Foreach($arr as $key => &$line)
{
If($line == $find)
{
Unset($arr[$key]);
shuffle($arr);
}
}
$writeToFile = fopen($inputFile,'w+');
$rewrittenList = trim($arr)."\n";
fwrite($writeToFile, $rewrittenList);
fclose($inputFile);
}
else {
echo "Email address check failed. Invalid email address entered. </br>
Line 55 occured.</br>";
#email addr entered wrong message
}
//asort(array) sorts array low to high (ascending)
//arsort(array) sorts array high to low (descending)
}
else
{
echo "Did not make it into filesize check. Filesize: $fileSize. Line 63 occured </br>";
}
}
}
else if (empty($fullName) or empty($emailAddr))
{
echo "Error! Line 23: One of the inputs was left empty. Line 69 occured </br>";
}
else
{
echo "Error! Line 23: Did not detect any values in either data area,</br>and program
did not go into first error. Line 73 occured </br>";
}
?>
<br>
</body>
</html>
I think you have overcomplicated it.
I foreach each line and check if it matches.
If it does I unset the line.
After the loop I implode on new line and the string is back to normal but without the $find's.
$str = "Matt Person emailaddr#email.com
John doe doesoe#gmail
Matt Person emailaddr#email.com
Trump donald#whitehouse";
$find = "Matt Person emailaddr#email.com";
$arr=explode("\n", $str);
Foreach($arr as $key => &$line){
If($line == $find){
Unset($arr[$key]);
}
}
Echo implode("\n", $arr);
https://3v4l.org/hmSr7

PHP foreach is stopping after first iteration

I have form where I have three inputs for files. With code below, I try to move files from TMP localisation to ./uploads with some random hash and name of file.
I have issue with foreach because it is stopping, after first iteration and saving file to uploads directory. I do not know why it is not happening for other two elements in table. Whole function below, it is a little mess, but I hope it is understandable.
function saveFile(){
global $patchFile;
$fileArray = [ $_FILES['file_one']['name'], $_FILES['file_two']['name'], $_FILES['file_three']['name'] ];
$tmpArray = [ $_FILES['file_one']['tmp_name'], $_FILES['file_two']['tmp_name'], $_FILES['file_three']['tmp_name'] ];
$multiArray =
[
[$_FILES['file_one']['name'], $_FILES['file_one']['tmp_name']],
[$_FILES['file_two']['name'], $_FILES['file_two']['tmp_name']],
[$_FILES['file_three']['name'], $_FILES['file_three']['tmp_name']]
];
foreach ($multiArray as $key)
{
echo "<br />Key: ".$key[0]."\n";
echo "Key_tmp: ".$key[1]."\n";
$randomString = generateRandomString();
$patchFile = './uploads/'.$randomString.$key[0];
echo "<br />Check patchFile: $patchFile";
if(is_uploaded_file($key[1]))
{
echo "<br />Begin uploading to directory...<br />";
if(!move_uploaded_file($key[1], $patchFile))
{
echo 'Problem: Nie udało się skopiować pliku do katalogu.';
return false;
}
else {
echo "File was saved in uploads directory";
return true;
}
}
else
{
echo "Uploading to directory... FAILED!";
}
}
}
When you return something from a loop, the loop is always broken.
As per PHP manual:
If called from within a function, the return statement immediately ends execution of the current function, and returns its argument as the value of the function call.

Accessing array values created in foreach loops

I am trying to display an error if a file does not upload. The crux of my problem is that my $status() array doesn't return the values I append in an if statement within a foreach loop.
Can someone enlighten me as to what is going on and what I am doing wrong? I'd like the status values in the foreach loop to append and return outside the loop.
Code below.
$status = array();
// Check that file within size restrictions, then upload.
foreach($request->getFiles() as $file)
{
$file_dir = sfConfig::get("sf_data_dir") . '/retail/order/' . $order_id . '/';
if (!is_dir($file_dir))
{
mkdir($file_dir, 0777, true);
}
$maxsize = 332027;
if(($file['size'] >= $maxsize) || ($file['size'] == 0))
{
$status[] = 0;
}
else
{
move_uploaded_file($file['tmp_name'], $file_dir . $file['name']);
$attachment = new Attachment();
$attachment->setName($file['name']);
$attachment->setPath($file_dir);
$attachment->setSize($file['size']);
$attachment->setCreatedTs('now');
$attachment->save();
$app_attachment = new ApendedAttachment();
$app_attachment->setAttachmentId($attachment->getAttachmentId());
$app_attachment->setWebOrderId($order_id);
$app_attachment->setCreatedTs('now');
$app_attachment->save();
$status[] = 1;
}
}
if (in_array(1, $status))
{
$this->getUser()->setFlash('success', 'Thank you. Your cart has been saved.');
}
else
{
$this->getUser()->setFlash('error', 'Please upload files less than 20MB.');
}
$this->redirect('order/detail?id=' . $order->getWebOrderId());
You are not assigning values to the status array correctly. You probably want to increment an index as you go through the array of files:
$i = 0;
for each(){
...
$status[$i] = 1;
...
$i++;
}
Sorry for the bad code format. Doing this on my mobile device.

if TXT empty echo message possible?

Hi I have a piece of code that is able to delete each newline in a txt file. Now my question is if the txt file is empty it gives an error message that $line doesn't exist. Now i want to add a piece off code that if txt has no content it echo's a message like "no emails in the list"
<?php
$delete = #$_GET['delete'];
$textFile = file("../emaillist/emaillist.txt");
$lines = count($textFile);
if($delete != "" && $delete >! $lines || $delete === '0') {
$textFile[$delete] = "";
$fileUpdate = fopen("../emaillist/emaillist.txt", "wb");
for($a=0; $a<$lines; $a++) {
fwrite($fileUpdate, $textFile[$a]);
}
fclose($fileUpdate);
echo"<p class='accept'>Contact verwijderd!</p>";
exit;
}
foreach($textFile as $key => $val) {
$pre= "<label style='float:left;' class='tablog3a'>";
$line = #$line . $pre . $val . "</label><a style='float:right;' href =?delete=$key><img class='clickreverse' src='images/deletetodo.png'></a><br>";
}
echo $line;
?>
I allready tried:
else {
echo "no emails in the list";
}
but that gave nothing....
I can think of a few ways to check if a file is empty:
$textfile = file('text.txt');
$lines = count($textfile);
if (empty($lines))
echo 'file is empty';
Or:
if (filesize('text.txt') === 0)
echo 'file is empty';
Or, if you want to check if it is empty, not including blank lines or extra whitespace:
$textfile = trim(file_get_contents('text.txt'));
if (empty($textfile))
echo 'file is empty';

A peculiar newbie debugging

It is one of the things I should have the know how but it really bugs. I have a large script which automates several tasks. It starts with uploading of files after which data from the files are extracted and then imported into mysql. In debugging mode it works perfectly but on my web front-end, execution stops after the data from the uploaded file is extracted. It never reaches the importation into database phase.
I realised that I had used this particular code below which I hold suspect:
$newFilePath = $upload_directory."/".$inFileName;
//opening the input file
if($inFileName != "")
$inputFile = fopen($newFilePath,"r");
else exit(1);
if(!$inputFile)
exit(0);
while(!feof($inputFile)) {
It is obvious that the exit() as used terminates the scripts thereby leaving out the lines that is handling the import of data into mysql.WIth the above, the upload works and the data separation carried out but the import never got executed. After some study I reviewed that portion by doing something quite appropriate like:
if (file_exists($inFileName)){
$inputFile = fopen($newFilePath,"r");
}
else {
echo "No file found ";
}
if (is_readable($inputFile)){
echo " ";
}else {
echo 'The file could not be read';
}
Now this piece of code review did not get me anyway as the upload is not even possible.
Now my problem is to fix this little portion of the code so I get the other parts of the script after it to do the import. It has been a nightmare for a beginner like me. I would appreciate if someone could review the above portion in a different way. I hope to see something that is similar or different but valid. I have learnt tougher stuff than this but this is simply nuts. I hope someone could understand my explanation. Thanks
New Edit.
if (is_array($inFilesArray)) {
foreach($inFilesArray as $inFileName) {
$numLines = 1;
$newFilePath = $upload_directory."/".$inFileName;
//opening the input file
if (file_exists($newFilePath)){
if (is_readable($newFilePath)){
$inputFile = fopen($newFilePath,"r");
}
} else {
echo "File not accessable";
}
//reading the inFile line by line and outputting the line if searchCriteria is met
while(!feof($inputFile)) {
$line = fgets($inputFile);
$lineTokens = explode(',',$line);
// Assign Device ID
switch ($lineTokens[0]){
case "IMEI 358998018395510\r\n":
$device_id = 1;
break;
case "IMEI 352924028650492\r\n":
$device_id = 3;
break;
case '$GPVTG':
$device_id = 2;
break;
}
if(in_array($lineTokens[0],$searchCriteria)) {
if (fwrite($outFile4, $device_id . "," .$line)===FALSE){
echo "Problem writing files\n";
}
$time = $lineTokens[1];
$date = $lineTokens[9];
$numLines++;
}
// Defining search criteria for $GPGGA
$lineTokens = explode(' ',$line);
$searchCriteria2 = array('OutCell');
if(in_array($lineTokens[0],$searchCriteria2)) {
if (fwrite($outFile5, $time.",".$date."\n")===FALSE){
echo "Problem writing to file\n";
}
}
}
fclose($inputFile);
}
Entire Script
<?php
#This script has threee parts: The first handles the uploaded files while the second part retrieves all RMCs and Handover dates and the 3rd handles importation of the data into their respective table in mysql database.
# This part uploads text files
include 'setamainfunctions.php';
if (isset($_POST['uploadfiles'])) {
$number_of_uploaded_files = 0;
$number_of_moved_files = 0;
$uploaded_files = array();
$upload_directory = dirname(__file__) . '/Uploads/';
//echo count($_FILES['uploadedFile']['name'])." uploaded ";
for ($i = 0; $i < count($_FILES['uploadedFile']['name']); $i++) {
//$number_of_file_fields++;
if ($_FILES['uploadedFile']['name'][$i] != '') { //check if file field empty or not
$number_of_uploaded_files++;
$uploaded_files[] = $_FILES['uploadedFile']['name'][$i];
//if (is_uploaded_file($_FILES['uploadedFile']['name'])){
if (move_uploaded_file($_FILES['uploadedFile']['tmp_name'][$i], $upload_directory . $_FILES['uploadedFile']['name'][$i])) {
$number_of_moved_files++;
}
}
}
echo "Number of files submitted $number_of_uploaded_files . <br/>";
echo "Number of successfully moved files $number_of_moved_files . <br/>";
echo "File Names are <br/>" . implode("<br/>", $uploaded_files)."\n";
echo "</br>";
echo "<p> Please find the processed RMCs and corresponding handovers as text files named:outputRMCs.txt and OutputHandovers.txt in the Setapro project root folder</p>";
/* echo "<br/>";
echo "<br/>";
echo "<p> Result of Mobile GPRMCs Transaction";
//echo "Total entries imported:.$numlines . <br/>";
echo "Data extraction and import mobile mobile GPRMCs successfuly completed";
echo "<br/>";
echo "<br/>";
echo "<p> Result of Handover Transaction";
//echo "Total entries imported:.$numlines . <br/>";
echo "Data extraction and imports for mobile handovers successfuly completed";*/
}
# This is the start of a script which accepts the uploaded into another array of it own for extraction of GPRMCs and handover dates.
$searchCriteria = array('$GPRMC');
//creating a reference for multiple text files in an array
/*if(isset($_FILES['uploadedFile']['name']))
$_FILES['uploadedFile'] = '';
}else {
echo "yes";
}*/
$inFilesArray = ($_FILES['uploadedFile']['name']);
//$inFiles = fopen($_FILES['uploadedFile']['tmp_name'], 'r');
//This opens a textfile for writing operation and puts all the entries from the multiple text files into one distinct textfile
if( ($outFile4 = fopen("outputRMCs.txt", "a")) === false ){
echo " ";
}
$outFile5 = fopen("outputHandovers.txt", "a");
//processing individual files in the array called $inFilesArray via foreach loop
if (is_array($inFilesArray)) {
foreach($inFilesArray as $inFileName) {
$numLines = 1;
$newFilePath = $upload_directory."/".$inFileName;
$correctFile = false;
//opening the input file
if (file_exists($newFilePath)){
if (is_readable($newFilePath)){
$inputFile = fopen($newFilePath,"r");
$correctFile = true;
}
}
if (!$correctFile)
echo "File not accessable";
//reading the inFile line by line and outputting the line if searchCriteria is met
while(!feof($inputFile)) {
$line = fgets($inputFile);
$lineTokens = explode(',',$line);
// Assign Device ID
switch ($lineTokens[0]){
case "IMEI 358998018395510\r\n":
$device_id = 1;
break;
case "IMEI 352924028650492\r\n":
$device_id = 3;
break;
case '$GPVTG':
$device_id = 2;
break;
}
if(in_array($lineTokens[0],$searchCriteria)) {
if (fwrite($outFile4, $device_id . "," .$line)===FALSE){
echo "Problem writing files\n";
}
$time = $lineTokens[1];
$date = $lineTokens[9];
$numLines++;
}
// Defining search criteria for $GPGGA
$lineTokens = explode(' ',$line);
$searchCriteria2 = array('OutCell');
if(in_array($lineTokens[0],$searchCriteria2)) {
if (fwrite($outFile5, $time.",".$date."\n")===FALSE){
echo "Problem writing to file\n";
}
}
}
fclose($inputFile);
}
//close the in files
fflush($outFile4);
fflush($outFile5);
}
fclose($outFile4);
fclose($outFile5);
#End of script for handling extraction
# This is the start of the script which imports the text file data into mysql database and does the necessary conversion.
$FilePath1 = $_SERVER["DOCUMENT_ROOT"] . '/setapro/outputRMCs.txt';
if (is_readable($FilePath1)) {
$handle = fopen($FilePath1, "r");
rmc_handoverHandler($handle);
echo "";
fclose($handle);
} else {
echo 'The file could not be read';
}
#Begining of script to handle imports into handover table
$FilePath2 = $_SERVER["DOCUMENT_ROOT"].'/setapro/outputHandovers.txt';
if (is_readable($FilePath2)) {
$handle = fopen($FilePath2, "r");
mobile_handoverHandler($handle);
echo "";
fclose($handle);
} else {
echo 'The file could not be read';
}
#End of script for handling imports into handover table
?>
It seems to me you want to do something more like this...
$newFilePath = $upload_directory."/".$inFileName;
$goodFile=false;
//Does the file exist?
if (file_exists($newFilePath)){
//If so, is it readable?
if (is_readable($newFilePath)){
//if it exists, and it readable, open it
$inputFile = file_get_contents($newFilePath);
//Don't display the error when done because file is good
$goodFile=true;
//Do Other stuff with file contents
}
}
if (!goodFile) echo "File Access Error";
You want to use newFilePath as it contains the path as well as the file name. The fact that you are checking for the file's existence and readability without also passing the file's path (only the file name) may be the cause of your issues.
UPDATE
try {
for ($i = 0; $i < count($_FILES['uploadedFile']['name']); $i++) {
//$number_of_file_fields++;
if ($_FILES['uploadedFile']['name'][$i] != '') {
$number_of_uploaded_files++;
$uploaded_files[] = $_FILES['uploadedFile']['name'][$i];
//if (is_uploaded_file($_FILES['uploadedFile']['name'])){
if (move_uploaded_file($_FILES['uploadedFile']['tmp_name'][$i], $upload_directory . $_FILES['uploadedFile']['name'][$i])) {
$number_of_moved_files++;
}
}
}
} catch (exception $e){
echo "General Error";
}

Categories