Replace strings in a file from an array in PHP - php

This is a tricky one...I am trying to replace some strings in a file that i hold in array.
Because there are a lot of files...i've been trying to find the fastest way possible.
I tried this (which worked) but it was slow.
First parsed all the files and got an array of the values i want to
change (lets say 500).
Then I wrote a foreach loop to parse through the files one by one.
Then inside that, another foreach loop to go through the values one by one
preg_replacing the file for any occurrences of the array value.
This takes forever though cause not all files need to be parsed with 500 array elements.
So i am changing the code now like this:
Parse every file and make an array of the values i want to replace.
Search the file again for all the occurrences for each array value and replace it.
Save the file
I think this will be much faster that the old way...The problem i am having though now is with the read/write loop, and the array loop...
I want to do this as fast as possible...cause there will be a lot of files to parse and some have 100+ values.
So far i got this in a function.
function openFileSearchAndReplace($file)
{
$holdcontents = file_get_contents($file);
$newarray = makeArrayOfValuesToReplace($holdcontents);
foreach ($newarray as $key => $value) {
$replaceWith = getNewValueFor($value);
$holdcontent = preg_replace('/\\b'.$value.'\\b/', $replaceWith, $holdcontents);
}
file_put_contents($file, $holdcontent, LOCK_EX); //Save and close
}
Now, this doesnt work...it just changes 1 value only because i have file_put_contents and file_get_contents outside of the foreach. (Not to mention that it replaces values that it shouldnt replace. Probably cause the read/write are outside of the loop.) I have to put them inside to work..but thats gonna be slow..cause it take 3-4seconds per file to do the change since there are a lot of elements in the array.
How can i "Open the file", "Read it", "Change ALL values first", "Then save close the file", so i can move to the next.
EDIT:
Maybe i am not explaining it well i dont know...or is this too complicated....I have to parse the array of values...there is no way i can avoid that...but instead of (In every loop), i open the file search and replace 1 value, close the file.....I want to do this:
Open the file, get the content in an array or string or whatever. For all the values i have keep replacing the text with the equivalent value, and when all the values are done...that array or string write to the file. So i am only opening/closing the file once. Instead of waiting for php to read/write/close all the time.
-Thanks

How about just using str_replace(mixed $search , mixed $replace , mixed $subject)?
You can have an array of search strings which will be replaced by their corresponding item in the replace array and as the PHP manual says:
If you don't need fancy replacing rules (like regular expressions), you should always use this function instead of preg_replace().
Also just close the file and reopen it with mode 'w'. File will be truncated to 0 length
Added Edit
$fileContents = file_get_contents("theFile");
$search = array('apples', 'oranges');
$replace = array('pears', 'lemons');
$newContents = str_replace($search, $replace, $fileContents);
$handle = fopen("theFile","w");
fwrite($handle, $newContents);
fclose($handle);
That's it your file has all the old strings replaced with new ones.

There is no solution to the problem. file_get_contents and file_put_contents simply doesnt work like that.
I appreciate everyone's attention to the problem.

Related

Can you write line by line to a PHP variable?

I have a script that generates Javascript based on user form inputs. At present the code is outputted to a txt file on the server, but I'd like to put it into a MySql database.
Writing line by line to a txt file is easy with fopen, and helpful with my script due to the way the code is generated and wrapped around user inputs (various loops etc).
However, I'd really like to write the output to a variable, and then send that to the database. However, I can't see any way of accomplishing this?
Im sure it is possible, but the information I've found online only deals with quite basic variable creation.
A dirty solution would be to write to the txt file as I currently do, and then load the text file into a variable and then delete the text file. But this seems silly and clearly a waste of processing time.
Very new to Php so sorry if the above seems dumb.
It's not too difficult, you can declare the variable with the first line and then incrementally write to it, with the \n escape sequence (representing a new line) separating each line. You can size use the PHP_EOL built-in inserted, as commented. The=` assignment operator appends the string following the operator to the variable's value prior to the operation.
$lines = "my first line";
while (condition) {
$lines .= PHP_EOL . "my next line";
}
A derivative way of doing this would be to insert all the lines inside the loop and start with just declaring an empty string.
$lines = "";
while (condition) {
$lines .= "my next line" . PHP_EOL;
}
Note that this method will add an empty newline at the end, which you can trim off of needed.
Alternatively, another way would be to create an array, push to it, and then use the implode function to glue together the array into a string using a newline.
$lines = array();
while (condition) {
array_push($lines, "my next line");
}
$lines = implode(PHP_EOL, $lines);

PHP Replace tags / placeholders / markers in text string with dynamic values

Basically, what I want to achieve is dynamically replace {SOME_TAG} with "Text".
My idea was to read all tags like {SOME_TAG}, put them into array.
Then convert array keys into variables like $some_tag, and put them into array.
So, this is how far I got:
//Some code goes here
$some_tag = "Is defined somewhere else.";
$different_tag = 1 + $something;
Some text {SOME_TAG} appears in different file, which contents has been read earlier.
//Some code goes here
preg_match_all('/{\w+}/', $strings, $search);
$search = str_replace(str_split('{}'),"",$search[0]);
$search = array_change_key_case( array_flip($search), CASE_LOWER);
...some code missing here, which I cant figure out.
Replace array should look something like this
$replace = array($some_tag, $different_tag);
//Then comes replacing code and output blah blah blah..
How to make array $replace contain variables dynamically depending on $search array?
Why not something along the lines of:
<?php
$replace = array(
'{TAG_1}' => 'hello',
'{TAG_2}' => 'world',
'{TAG_3}' => '!'
);
$myString = '{TAG_1} {TAG_2}{TAG_3}{TAG_3}';
echo str_replace(array_keys($replace), array_values($replace), $myString);
If I understand correctly:
You're working on trying to create a customizable document, using {TAGS} in order to represent replaceable areas that can be filled in with dynamic information. At some point in time while replacing the {TAGS} with the dynamic information, you want the dynamic information to be stored in automatically generated basic variable names, as $tags.
I'm not sure why you want to convert these tags to basic variables instead using them entirely as array keys. I would like to point out that this represents a security or functionality hole - what happens if someone puts {REPLACE} in as a tag in your document? Your replace array would get overwritten with dynamic data, and your whole program would fall apart. Either that, or the whole replace array would get dumped in for {REPLACE}, making for a very messy document with perhaps data you don't WANT them to have in it. Perhaps you have this dealt with - I don't have all the context here - but I thought I'd point out the risk factor.
As for a better solution, unless there's some specific need that you're addressing by going through $tags instead of using using the $replace array directly, I like #Emissary's answer.

php - delete words from array by matching external text file

I have an array and an external file, both contains lots of words. I want to match strings in the array with the entire external file. Then if there are identical words, I want to delete the word from the array.
Much shorten example:
$words = {"apple", "orange", "banana", "grape", "peach"}
The external text file is a pure list of words
apple
banana
melon
...
I'd like to delete the words that are in the external file, and finally get this.
$words = {"orange", "grape", "peach"}
Should I call the external file, slice every line, then save them to another array? Then compare with the source array?
What is the most effective way to compare the array and a text file?
I'd appreciate your wisdom!
You could use array_diff.(file to get an array from file.)
$result = array_diff($words, file('path_to_file', FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES));
PS: If your external text file is very big, and you don't want to load it to memory at one time, you could read it line by line, and check it whether it exists in the array.

How to add an array into a comma delimited text file without deleting previous array values

I'm trying to make a form where the user can add their own 'questions + answers' to the quiz.
I loaded the original questions from a text file. The added questions will then be processed by process_editadd.php
<?php
session_start();
$file = fopen('data.txt', 'r');
$array=$_SESSION['questions_array'];
//make array out of values
$q=array($_POST['question'],$_POST['one'],$_POST['two'],$_POST['three'],$_POST['four']);
//add to file
$file=fopen("data.txt","w+");
fwrite($file, implode(',', $q)).
header('Location:module.php');
?>
The array adds onto the text file, but the problem is that it replaces the whole thing. I don't want the questions to replace the previous ones, I just want them added. Do you guys know what's wrong with the code?
Note: I'm not allowed using mySQL or Javascript
You could switch to using an actual database and make your life a lot easier... Failing that, look into fputcsv and fgetcsv to make it a slightly less tedious problem.
Your implode version right now is also vulnerable to CSV injection... you don't handle the case where any of the text you're writing MIGHT contain a comma. If it does, you'll suddenly find you'll have extra "columns" when you read the data back in later on.

Reading specific CSV value in PHP

I have the following CSV file:
08-0018421032;00-0018151831;G-20009429-0;G-20009429-0;0374048-0
27-001842101232;10-0018151831;G-30009429-0;G-50009429-0;7374048-0
36-0018421033232;20-0018151831;G-40009429-0;G-60009429-0;8374048-0
As you can see the separator is the ; symbol.
I then send this info to php via a jquery plugin which works perfect since I can read the file in PHP. The following code grabs the CSV file (Which is the $csvfile variable) and I can see the lines in it:
$file = fopen("upload/$csvfile", "r");
while (!feof($file) ) {
$line = fgetcsv($file, 1024,';');
print $line[0].'<br/>';
}
fclose($file);
What I need is to be able to select not only the line but on the value in it. To go to a specific value, for example in the first line the 3rd value would be G-20009429-0 and I would assign this to a php variable to be used later on.
Right now I have no idea how to grab a specific value in a line and also when I print the $line[0] it shows the values in a vertical order instead of a horizontal order. What I mean with this is that it shows the following output:
00-0018151831
10-0018151831
20-0018151831
Instead of showing me like this:
08-0018421032;00-0018151831;G-20009429-0;G-20009429-0;0374048-0
Maybe is the sleep but am stuck here. Just to repeat, the csv file is read by Php correctly since I can do a print_r on it and it shows all the lines in it. The thing is how to manipulate the information after I have the csv and how to grab a specific value in a specific line. Thank you.
$line is an array containing every element from that row. $line[0] is the first element of the row, $line[1] the second element and so on. Try var_dump($line). What you're doing is you output every first element of every row.
If you want to output every element in one line, just concatenate the array again:
echo join(';', $line);
But then that's missing the point of fgetcsv, which is specifically helpfully separating those elements into an array for you so you can work with them.

Categories