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
Related
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! :)
I am trying to create a CSV Checker which inserts the checked data into a Database and any unsuccessful data added to a .txt file.
I am trying to used regular expressions to validate the data I am inserting, the while loop without any validation works and inserts fine but as soon as regular expressions are used it does not work.
<?php
include_once('connection.php');
error_reporting(E_ALL);
date_default_timezone_set('Europe/London');
$date = date('d/m/y h:i:s a', time());
$filetxt = "./errors.txt";
$errors = array();
$var1 = 5;
$var2 = 1000;
$var3 = 10;
$sql = '';
if(isset($_POST["Import"]))
{
echo $filename=$_FILES["file"]["tmp_name"];
if($_FILES["file"]["size"] > 0)
{
$file = fopen($filename, "r");
while(($emapData = fgetcsv($file, 10000, ",")) !==FALSE)
{
if(isset($_GET['strProductCode']))
{
$emapData[0] = $conn->real_escape_string(trim($_POST['strProductCode']));
if (!preg_match("^[a-zA-Z0-9]+$^", $_POST['strProductCode']))
{
$errors['strProductCode'];
}
}
if(isset($_GET['strProductName']))
{
$emapData[1] = $conn->real_escape_string(trim($_GET['strProductName']));
if (!preg_match("^[a-zA-Z0-9]+$^", $_POST['strProductName']))
{
$errors['strProductName'];
}
}
if(isset($_GET['strProductDesc']))
{
$emapData[2] = $conn->real_escape_string(trim($_GET['strProductDesc']));
if (!preg_match("^[a-zA-Z0-9]+$^", $_POST['strProductDesc']))
{
$errors['strProductDesc'];
}
}
if(isset($_GET['intStock']))
{
if (!preg_match("^[0-9]", $_POST['intStock']))
{
$errors['intStock'];
}
}
if(isset($_GET['intPrice']))
{
if (!preg_match("[0-9]", $_POST['intPrice']))
{
$errors['intPrice'];
}
}
if(isset($_GET['dtmDiscontinued'])){
if($emapData[6] == preg_match("[a-zA-Z]", $_POST['dtmDiscontinued']))
{
$emapData[6] = $date;
echo $date;
}else{
$emapData[6] = Null;
}
}
if(count($errors > 0))
{
// errors
$write = "$emapData[0], $emapData[1], $emapData[2], $emapData[3], $emapData[4], $emapData[5], $emapData[6]\r\n";
file_put_contents($filetxt , $write , FILE_APPEND);
}else{
// insert into Database
$sql = "INSERT INTO tblproductdata(strProductCode, strProductName, strProductDesc, intStock, intPrice, dtmAdded, dtmDiscontinued) VALUES('$emapData[0]','$emapData[1]','$emapData[2]','$emapData[3]','$emapData[4]','$date','$emapData[6]')";
$res=$conn->query($sql);
}
}
fclose($file);
echo "CSV File has successfully been Imported";
echo "<br>";
echo "Any errors within the CVS Database are reported here.";
echo "<br>";
$fh = fopen($filetxt, 'r');
$theData = fread($fh, filesize($filetxt));
fclose($fh);
echo $theData;
}else{
echo "Invalid File: Please Upload a Valid CSV File";
}
header("Location: index.php");
}
?>
My knowledge of PHP is not great but this is my best attempt.
Any help would be greatly appreciated.
There are several issues in your code. Let's start with the regular expressions and your error checking:
Some of your expressions are invalid. Note that each expression needs a delimiting character at the beginng and ending of the expression. In some of your expressions (like ^[0-9]) these delimiters are missing. Please also note that using ^ as a delimiter for a regular expression is not a good choice, because the ^ character also has a special meaning in regular expressions.
This should actually cause PHP Warnings. I see that you have error_reporting enabled; you should also have a look at your display_errors setting.
As mentioned in my comment, you do not assign any values to the $errors array. The statement $errors['strProductName'] in itself does not change the array; this means that $errors will always be empty. You probably mean to do something like:
$errors['strProductName'] = TRUE;
You're actually checking count($errors > 0) where you should be checking count($errors > 0). count($errors > 0) translates to either count(TRUE) or count(FALSE) which both equal 1.
Some other notes:
Some times, you check for $_GET['strProductCode'], but then use $_POST['strProductCode'].
You do not reset the $errors array for each iteration. That means that for each line that you read, the $errors variable will still contain the errors from the previous iteration. As a result, the first invalid line will cause all following lines to be recognized as invalid, too.
You register an error when one of the parameters is of an invalid format, but not when one of them is not set at all (i.e. when isset($_POST[...]) is FALSE). Each of them should probably be sth. like this:
if (isset($_POST['strProductCode'])) {
$emapData[0] = $conn->real_escape_string(trim($_POST['strProductCode']));
if (!preg_match("^[a-zA-Z0-9]+$^", $_POST['strProductCode'])) {
$errors['strProductCode'] = TRUE;
}
} else {
$errors['strProductCode'] = TRUE;
}
I tried to write this program to compare a user-name in a file with an entered user-name to check whether it exists, but the program doesn't seem to work. Please help. The program was supposed to open a file called allusernames to compare the usernames. If the user name was not found, add it to the file.
<?php
$valid=1;
$username = $_POST["username"];
$listofusernames = fopen("allusernames.txt", "r") or die("Unable to open");
while(!feof($listofusernames)) {
$cmp = fgets($listofusernames);
$val = strcmp($cmp , $username);
if($val == 0) {
echo ("Choose another user name, the user name you have entered has already been chosen!");
$valid=0;
fclose($listofusernames);
break;
} else {
continue;
}
}
if($valid != 0) {
$finalusers = fopen("allusernames.txt", "a+");
fwrite($finalusers, $username.PHP_EOL);
fclose($finalusers);
?>
you need to replace linefeed/newline character from each line to compare.
while(!feof($listofusernames)) {
$cmp = fgets($listofusernames);
$cmp = str_replace(array("\r", "\n"), '',$cmp);
$val = strcmp($cmp , $username);
if($val == 0) {
echo ("Choose another user name, the user name you have entered has already been chosen!");
$valid=0;
fclose($listofusernames);
break;
} else {
continue;
}
}
i have added following line in you code
$cmp = str_replace(array("\r", "\n"), '',$cmp);
I havent tested this but I wonder if you could use something like
<?php
$user = $_POST["username"];
$contents = file_get_contents("allusernames.txt");
$usernames = explode("\n",$contents);
if(in_array($user,$usernames))
{
echo "Choose another username";
}
else
{
$contents .= "\n".$user;
file_put_contents("allusernames.txt",$contents);
}
I think things like file get contents etc. need a certain version of PHP but they do make things a lot nicer to work with.
This also assumes that your usernames are seperated by new lines.
Yo can do this more simple with this code:
<?php
$username = $_POST["username"];
$listofusernames = 'allusernames.txt';
$content = file($listofusernames);
if(in_array($username, $content)) {
echo ("Choose another user name, the user name you have entered has already been chosen!");
} else {
$content[] = $username . PHP_EOL;
file_put_contents($listofusernames, implode('', $content));
}
?>
I wrote a program that creates a puzzle based on user's inputs. There is a html form that accepts the user's words and posts them to the php program. Then the php program creates the puzzle and prints it.
There is a live demo here. You can type you own words.
It looks good but when I run it in my local server with php error prompt turned on, I see the error msg saying Undefined offset: 10 at line 147 and 148. The error is generated from the php code line starting from if ($board[$curr_row][$curr_col] == '.'... You can use Ctrl+F to find the code. I don't understand how could I get 10 in $curr_col or $curr_row since the loop should stop after they reach 9.
Please help me understand how could the loop run after they have reached 10, thanks a lot!
The zipped version of the program is here.
Here is the code of the php:
<html>
<body>
<?php
/* word Find
Generates a word search puzzle based on a word list entered by user.
User can also specify the size of the puzzle and print out
an answer key if desired
*/
//If there is no data from the form, prompt the user to go back
if (!filter_has_var(INPUT_POST, "puzzle_name")) {
print <<<MUL_LINE
<!DOCTYPE html>
<html >
<head>
<title>Oops!</title>
</head>
<body>
<p>This page should not be called directly, please visit
the puzzle form to continue.</p>
</body>
</html>
MUL_LINE;
} else {
$boardData = array("name" => filter_input(INPUT_POST, "puzzle_name"), "width" => filter_input(INPUT_POST, "grid_width"), "height" => filter_input(INPUT_POST, "grid_height"));
if (parseList() == TRUE) {//parse the word list in textarea to an array of words
//keep trying to fill the board untill a valid puzzle is made
do {
clearBoard();
//reset the board
$pass = fillBoard();
} while($pass == FALSE);
printBoard();
//if the board if successfully filled, print the puzzle
}
}//end word list exists if
//parse the word list in textarea to an array of words
function parseList() {
//get word list, creates array of words from it
//or return false if impossible
global $word, $wordList, $boardData;
$wordList = filter_input(INPUT_POST, "wordList");
$itWorked = TRUE;
//convert word list entirely to upper case
$wordList = strtoupper($wordList);
//split word list into array
$word = explode("\n", $wordList);
//an array of words
foreach ($word as $key => $currentWord) {
//trim all the beginning and trailer spaces
$currentWord = rtrim(ltrim($currentWord));
//stop if any words are too long to fit in puzzle
if ((strlen($currentWord) > $boardData["width"]) && (strlen($currentWord) > $boardData["height"])) {
print "$currentWord is too long for puzzle";
$itWorked = FALSE;
}//end if
$word[$key] = $currentWord;
}//end foreach
return $itWorked;
}//end parseList
//reset the board by filling each cell with "."
function clearBoard() {
//initialize board with a . in each cell
global $board, $boardData;
for ($row = 0; $row < $boardData["height"]; $row++) {
for ($col = 0; $col < $boardData["width"]; $col++) {
$board[$row][$col] = ".";
}//end col for loop
}//end row for loop
}//end clearBoard
//fill the board
function fillBoard() {
global $word;
$pass = FALSE;
//control the loop of filling words, false will stop the loop
//control the loop, if all the words are filled, the counter will be as equal to the number
//of elements in array $words, thus the loop stops successfully
$counter = 0;
do {
$pass = fillWord($word[$counter]);
//if a word is filled, $pass is set to true
$counter++;
}
//if a word can't be filled, pass==FALSE and loop stops
//or if all words are through, loop stops
while($pass==TRUE && $counter<count($word));
//return TRUE if all filled successfully, FALSE if not
if ($pass == TRUE && $counter == count($word)) {
return TRUE;
} else {
return FALSE;
}
}
//function used to fill a single word
function fillWord($single_word) {
global $board, $boardData;
//the direction of how the word will be filled, 50% chance to be H, and 50% chance to be V
$dir = (rand(0, 1) == 0 ? "H" : "V");
//H(horizontal) means fill the word from left to right
//V(vertical) means fill the word from up to down
//loop control. if a letter is not filled, $pass is set to false and loop stops
$pass = TRUE;
//loop control. if all letters are filled successfully, loop stops too.
$counter = 0;
//decide the cell to fill the first word. the cell is located at $board[$curr_row][$curr_col]
if ($dir == "H") {//if the word will be fileld from left to right
$curr_row = rand(0, $boardData["height"] - 1);
//pick up a random row of the 10 rows ( rand(0,9) )
$curr_col = rand(0, ($boardData["width"] - ( strlen($single_word - 1)) - 1));
//pick up a random column of fillable columns
//if the word is "banana" and the board's width
//is 10, the starting column can only be rand(0, 4)
} else if ($dir == "V") {//if the word will be fileld from up to down
$curr_row = rand(0, ($boardData["height"] - ( strlen($single_word - 1)) - 1));
$curr_col = rand(0, $boardData["width"] - 1);
} else {
print "invalid direction";
}
//the loop that keeps trying to fill letters of the word
while ($pass && ($counter < strlen($single_word))) {//while the $pass is true AND there are still letters
//to fill, keep the loop going
//the next line and the line after generate the msg "Undefined offset: 10",
//$curr_row and $curr_col should never be 10 because the loop should be stopped
//if the last letter of the word is filled
if ($board[$curr_row][$curr_col] == '.' || //if the cell is not filled, reset fillboard() to "."
$board[$curr_row][$curr_col] == substr($single_word, $counter, 1))//or it has already been filled with the same letter
{
$board[$curr_row][$curr_col] = substr($single_word, $counter, 1);
// write/fill the letter in the cell
$counter++;
if ($dir == "H") {
$curr_col++;
//next column, move to the next right cell
} else if ($dir == "V") {
$curr_row++;
//next row, move to the next lower cell
} else {
print "\nHuge direction error!";
}
} else {
$pass = FALSE;
// failed to fill a letter, stop the loop
}
}
//if all the letters are filled successfully, the single word is filled successfully
//return true, let $fillBoard go filling next single word
if ($pass && ($counter == strlen($single_word))) {
/* for debug purpose
print "<hr />";print "<p>TRUE</p>";print "<hr />";
print $single_word;
print $curr_row . "," . $curr_col . "<br />";
print "<hr />";*/
return TRUE;
} else {
//failed to fill the word, reset the board and start all over again
return FALSE;
}
}//end function fillWord
//print the successful filled puzzle
function printBoard() {
global $board;
print <<<MULLINE
<style type="text/css">
table, td{
border: 1px solid black;
}
</style>
MULLINE;
print '<table >';
foreach ($board as $row) {
print '<tr>';
foreach ($row as $cell) {
print '<td>';
print $cell;
print '</td>';
}
print("<br />");
print '</tr>';
}
print "</table>";
}
?>
</body>
</html>
I don't think the following fragment of code is right.
strlen($single_word - 1)
located in the lines:
$curr_col = rand(0, ($boardData["width"] - ( strlen($single_word - 1)) - 1));
and
$curr_row = rand(0, ($boardData["height"] - ( strlen($single_word - 1)) - 1));
It will convert the word to an integer. Subtract one from that number. Then convert that back to a string and take the length. So you have a rubbish value for the length.
Basically I want to echo only summary of my blog post on a certain page by making a function() that must limit the number of counts of words as specified there.
function sumarize($your_string){
$count++;
$maximum = 10;
foreach(explode("\n", $your_string) as $line){
$count++;
echo $line."\n";
if ($count == $maximum) break;
}
}
Lets say your table (named main) looks like that.
id | blogpost
1 sample1
2 sample2
...
At first you need to connect to db
$db=NEW MYSQLI('localhost', 'username', 'pass', 'dbname') or die ($db->error);
Then write following piece of code
function sumarize($your_string){
$count++;
$maximum = 10;
foreach(explode("\n", $your_string) as $line){
$count++;
echo $line."\n";
if ($count == $maximum) break;
}
}
$result=$db->query("SELECT `id`, `blogpost` FROM `main`");
while($row->fetch_object()){
echo sumarize($row->blogpost);
}
This is how to get work genesis φ's solution
this one takes into account numbers of character whilst ending at the last word without cutting out a character
use
select .... SUBSTR(body,1,300) .....
later you can use this function in php to cut the string at the last space or period so you wont get a half cut word in the end. The second parameter is the number of characters you want.
function shorten_string($string, $characters)
{
$shortened_string = "";
$smaller_string = substr($string, 0, $characters);
$pos_of_last_space = strrpos($smaller_string, " ");
$pos_of_last_break = strrpos($smaller_string, " ");
if (strlen($string) <= $characters) {
$shortened_string = $string;
} elseif (!$pos_of_last_space && !$pos_of_last_break) {
$shortened_string = $smaller_string;
} else {
$break_at = 0;
if ($pos_of_last_space > $pos_of_last_break) {
$break_at = $pos_of_last_space;
} else {
$break_at = $pos_of_last_break;
}
$shortened_string = substr($smaller_string, 0, $break_at);
}
}
NOTE: takes care of spaces put in html with 'nbsp'
Save the summary and body of your blog posts in different columns.