So I want to search a text file which contains a list of suburbs with names and postcodes. Depending on the the postcode given I want to display the suburb. I know I'm suppose to loop through the text file but have no idea how to actually search for exact value in the line and then display a different part of that same line. I know that I can use the explode function and get the part of the string I want but what I don't know how to do is loop through the file and finding the exact line of it.
Any Help on this is most Appreciated !
Thanks !
Since you didn't provide any example of what you have tried so far, this may not completely match what you are doing.
Assuming a file suburbs.txt with contents like:
Somewhere,12345
Somewhere Else,12346
This Place,12347
There,12348
You could do the following to loop through the entries:
$zipCode = '12346';
$lines = file('/path/to/suburbs.txt');
foreach ( $lines as $line )
{
$fields = explode( ',', $line );
if ( $fields[1] == $zipCode )
{
echo "Your suburb is: " . $fields[0];
break;
}
}
file() loads a file into an array. This is what allows you to loop through using foreach(). There are other methods of doing this as well, but this should help you move in the right direction.
Related
I am new to the world of coding and learning PHP these days. For almost one week of research on this issue , I have almost given up on this issue. Hope to get some good insight on it from the experts.
Problem :- I have a CSV file which has information about servers. for Example :
ClientId,ProductName,Server,ServerRole,Webserver,DatabaseName
001,abc,Server1,Web,Webserver1,,
001,abc,Server2,Dabatase,,Database1
001,abc,Server3,Application,,,
002,abc,Server4,Web,Webserver2,,
002,abc,Server5,Database,,Database2,
I created a HTML page which has a simple html form which takes a server name as an input and invokes the commands written in a page called "search.php". I am able to save the user input from index form to a variable fine . But here is the real problem. I want to search that variable against this CSV file , find the client name ( column 1) related to that server ( which should be matched from column 3 ) and then , print all the lines for that client. For e.g. if I input "Server3" , I should get the first three lines as output in a table form.
I have used fgetcsv() , fgets() etc. but I dont seem to crack this. So far , the closest I have reached is printing all the lines which contain the input text (and that too not in a table form). Any help to resolve my problem would be much appreciated.
Here is my code so far:
<?php
$name = $_POST["search"];
echo "You have searched for the server <b>$name</b>";
$output = "";
$fp = fopen("D:\VMware\DSRM\Servers\Servers.csv", "r");
// Read file
$txt = fgets($fp);
while ( !feof( $fp ) ) {
// Search for keyword
if ( stripos( $txt, $name ) !== false ) {
$output .= $txt.'<br />';
}
$txt = fgets($fp);
}
echo $output;
?>
What about regex?
$input_lines = file_get_contents("theCSV");
$server = "Server3";
preg_match_all("/(\d+).*(".$server.")(.*)/", $input_lines, $clientid);
preg_match_all("/(". $clientid[1] .".*)/", $input_lines, $output_array);
Var_dump(output_array[1]);
In theory this should work :-)
I was using a script to exclude a list of words from another list of keywords. I would like to change the format of the output. (I found the script on this website and I have made some modification.)
Example:
Phrase from outcome: my word
I would like to add quotes: "my word"
I was thinking that I should put the outcome in new-file.txt and after to rewrite it, but I do not understand how to capture the result. Please, kindly give me some tips. It's my first script :)
Here is the code:
<?php
$myfile = fopen("newfile1.txt", "w") or die("Unable to open file!");
// Open a file to write the changes - test
$file = file_get_contents("test-action-write-a-doc-small.txt");
// In small.txt there are words that will be excluded from the big list
$searchstrings = file_get_contents("test-action-write-a-doc-full.txt");
// From this list the script is excluding the words that are in small.txt
$breakstrings = explode(',',$searchstrings);
foreach ($breakstrings as $values){
if(!strpos($file, $values)) {
echo $values." = Not found;\n";
}
else {
echo $values." = Found; \n";
}
}
echo "<h1>Outcome:</h1>";
foreach ($breakstrings as $values){
if(!strpos($file, $values)) {
echo $values."\n";
}
}
fwrite($myfile, $values); // write the result in newfile1.txt - test
// a loop is missing?
fclose($myfile); // close newfile1.txt - test
?>
There is also a little mistake in the script. It works fine however before entering the list of words in test-action-write-a-doc-full.txt and in test-action-write-a-doc-small.txt I have to put a break for the first line otherwise it does not find the first word.
Example:
In test-action-write-a-doc-small.txt words:
pick, lol, file, cool,
In test-action-write-a-doc-full.txt wwords:
pick, bad, computer, lol, break, file.
Outcome:
Pick = Not found -- here is the mistake.
It happens if I do not put a break for the first line in .txt
lol = Found
file = Found
Thanks in advance for any help! :)
You can collect the accepted words in an array, and then glue all those array elements into one text, which you then write to the file. Like this:
echo "<h1>Outcome:</h1>";
// Build an array with accepted words
$keepWords = array();
foreach ($breakstrings as $values){
// remove white space surrounding word
$values = trim($values);
// compare with false, and skip empty strings
if ($values !== "" and false === strpos($file, $values)) {
// Add word to end of array, you can add quotes if you want
$keepWords[] = '"' . $values . '"';
}
}
// Glue all words together with commas
$keepText = implode(",", $keepWords);
// Write that to file
fwrite($myfile, $keepText);
Note that you should not write !strpos(..) but false === strpos(..) as explained in the docs.
Note also that this method of searching in $file will maybe give unexpected results. For instance, if you have "misery" in your $file string then the word "is" (if separated by commas in the original file) will be refused, as it is found in $file. You might want to review this.
Concerning the second problem
The fact that it does not work without first adding a line-break in your file leads me to think it is related to the Byte-Order Mark (BOM) that appears in the beginning of many UTF-8 encoded files. The problem and possible solutions are discussed here and elsewhere.
If indeed it is this problem, there are two solutions I would propose:
Use your text editor to save the file as UTF-8, but without BOM. For instance, notepad++ has this possibility in the encoding menu.
Or, add this to your code:
function removeBOM($str = "") {
if (substr($str, 0,3) == pack("CCC",0xef,0xbb,0xbf)) {
$str = substr($str, 3);
}
return $str;
}
and then wrap all your file_get_contents calls with that function, like this:
$file = removeBOM(file_get_contents("test-action-write-a-doc-small.txt"));
// In small.txt there are words that will be excluded from the big list
$searchstrings = removeBOM(file_get_contents("test-action-write-a-doc-full.txt"));
// From this list the script is excluding the words that are in small.txt
This will strip these funny bytes from the start of the string taken from the file.
I am looking for a way to grab details from a file name to insert it into my database. My issue is that the file name is always a bit different, even if it has a pattern.
Examples:
arizona-911545_1920.jpg
bass-guitar-913092_1280.jpg
eiffel-tower-905039_1280.jpg
new-york-city-78181_1920.jpg
The first part is always what the image is about, for example arizona, bass guitar, eiffel tower, new york city followed by a unique id and the width of the image.
What I am after would be extracting:
name id and width
So if I run for example getInfo('arizona-911545_1920.jpg');
it would return something like
$extractedname
$extractedid
$extractedwidth
so I could easily save this in my mysql database like
INSERT into images VALUES ('$extractedname','$extractedid','$extractedwidth')
What bothers me most is that image names can be longer, for example new-york-city-bank or even new-york-city-bank-window so I need a safe method to get the name, no matter how long it would be.
I do know how to replace the - between the name, that's not an issue. I am really just searching for a way to extract the details I mentioned above.
I would appreciate it if someone could enlighten me on how to solve this.
Thanks :)
One of the simplest way in this case is to use regexp, for example:
preg_match('/^(\D+)-(\d+)_(\d+)/', $filename, $matches);
// $matches[1] - name
// $matches[2] - id
// $matches[3] - width
This is the main Idea.
Let's pick a file first.
Filename will be "bass-guitar-913092_1280.jpg"
First of all we will Split this with explode, to dot( . ) in variable $Temp
This will give us an Array of bass-guitar-913092_1280 and jpg
We will choose to have the first Item of the array to continue since is the name we are interested in so we will get it with $Temp[0]
After this we will Split it Again this time to ( _ ).
Now we will have an array of bass-guitar-913092 and 1280
The Second value of the Array is what We need so we will pick it with $Temp[1]
The Last part is simple as the others, We will now Split the file name $Temp[0] with ( - ) We will get the Last value of it which is the id $Temp[count($Temp)-1] and we will remove this from the array list, and Connect everything else with implode and the delimeter we want
Now we can use also the Function ucwords to Capitalize every first letter of each word on the main name.
In the following code, there are 2 ways of getting the name, one with lowercase letters, and one with uppercase first letters of each word, uncomment what you want.
Edited Code as a Function
<?php
function ExtractFileInfo($fileName) {
$Temp = explode(".",$fileName);
$Temp = explode("_",$Temp[0]);
$width = $Temp[1];
$Temp = explode("-",$Temp[0]);
$id = $Temp[count($Temp)-1];
unset($Temp[count($Temp-1)]);
// If you want to have the name with lowercase letters Uncomment the Following:
//$name = implode(" ",$Temp);
// If you Want to Capitalize every first letter of the name Uncomment the Following:
//$name = ucwords(implode(" ",$Temp));
return array($name,$id,$width);
}
?>
This will return an Array of 3 Elements Name, Id and Width
Extracting the data you are looking for would be best via a regex pattern like the following:
(.+)-(\d+_(\d+))
Example here: https://regex101.com/r/oM5bS8/2
preg_match('(.+)-(\d+_(\d+))',"<filename>", $matches);
$extractedname = $matches[1];
$extractedid = $matches[2];
$extractedwidth = $matches[3];
EDIT - Just reread the question and you are looking for extraction techniques not how to post the image from a page to your backend. I will leave this here for reference.
When you post files via a form in html to a PHP backend there are few items that are needed.
1) You need to ensure that your form type is multi-part so that it knows to pass the files along.
<form enctype="multipart/form-data">
2) Your php backend needs to iterate over the files and save them accordingly.
Here is a sample of how to iterate over the files that are being submitted.
foreach($_FILES as $file) {
$n = $file['name'];
$s = $file['size'];
if (!$n) continue;
echo "File: $n ($s bytes)";
}
I have a folder (blogfiles/posts) with various text files, numbered (1.txt, 2.txt, 3.txt...) and they each hold a post for a blog (I haven't learned SQL yet). I'm trying to make a search engine for it that will take a query from a text box (done with this part), then search the files for each word in the query, and return the results (possibly in order of the number of times the word occurs).
Each text file looks like this:
Title on Line 1
Date Posted on Line 2 (in Month Date, Year form)
Post body to search on lines 3 and up
I currently have this code:
<?php
$q = $_GET["q"];
$qArray = explode(" ", $q);
//preparing files
$post_directory = "blogfiles/posts/";
$files = scandir($post_directory, 1);
$post_count = (count($files)) - 2;
$files = array_pop($files); // there are 2 server files I want to ignore (#1)
$files = array_pop($files); // there are 2 server files I want to ignore (#2)
foreach ($files as $file) {
//getting title
$post_path = $post_directory . $file;
$post_filecontents = file($post_path);
$post_title = $post_filecontents[0];
echo "<tr><td>" . $post_title . "</td></tr>";
}
if ($post_count > 2) {
$postPlural = "s";
}
echo "<tr><td>" . $post_count . " post" . $postPlural . ".";
?>
I'll apologize now for the formatting, I was trying to separate it to troubleshoot.
Any help to get this working would be greatly appreciated.
There are many ways to search files.
use preg_match_all function to match pattern for each file.
use system() function to run external command like grep (only available under *nix).
use strpos function ( not recommended because of low performance and lack of support of pattern ).
If you will face a big traffic you'd better use pre-build indexes to accelerate the search. for example split the posts into tokens ( words ) and add position info along with the words, when user search the some words you can just split the words first and then look for the indexes. It's simpler to discribe this method than to implement it. You may need a existing full-text search engine like Apache Lucene.
I am writing a php script that will parse through a file, (synonyms.dat), and coordinate a list of synonyms with their parent word, for about 150k words.
Example from file:
1|2
(adj)|one|i|ane|cardinal
(noun)|one|I|ace|single|unity|digit|figure
1-dodecanol|1
(noun)|lauryl alcohol|alcohol
1-hitter|1
(noun)|one-hitter|baseball|baseball game|ball
10|2
(adj)|ten|x|cardinal
(noun)|ten|X|tenner|decade|large integer
100|2
(adj)|hundred|a hundred|one hundred|c|cardinal
(noun)|hundred|C|century|one C|centred|large integer
1000|2
(adj)|thousand|a thousand|one thousand|m|k|cardinal
(noun)|thousand|one thousand|M|K|chiliad|G|grand|thou|yard|large integer
**10000|1
(noun)|ten thousand|myriad|large**
In the example above I want to link ten thousand, myriad, large to the word 1000.
I have tried various method of reading the .dat file into memory using file_get_contents and then exploding the file at \n, and using various array search techniques to find the 'parent' word and it's synonyms. However, this is extremely slow, and more often then not crashes my web server.
I believe what I need to do is use preg_match_all to explode the string, and then just iterate over the string, inserting into my database where appropriate.
$contents = file_get_contents($page);
preg_match_all("/([^\s]+)\|[0-9].*/",$contents,$out, PREG_SET_ORDER);
This matches each
1|2
1-dodecanol|1
1-hitter|1
But I don't know how to link the fields in between each match, IE the synonyms themselves.
This script is intended to be run once, to get all the information into my database appropriately. For those interested, I have a database 'synonym_index' which holds a unique id of each word, as well as the word. Then another table 'synonym_listing' which contains a 'word_id' column and a 'synomym_id' column where each column is a foreign key to synonym_index. There can be multiple synonym_id's to each word_id.
Your help is greatly appreciated!
You can use explode() to split each line into fields. (Or, depending on the precise format of the input, fgetcsv() might be a better choice.)
Illustrative example, which will almost certainly need adjustment for your specific use case and data format:
$infile = fopen('synonyms.dat', 'r');
while (!feof($infile)) {
$line = rtrim(fgets($infile), "\r\n");
if ( $line === '' ) {
continue;
}
// Line follows the format HEAD_WORD|NUMBER_OF_SYNONYM_LINES
list($headWord, $n) = explode('|', $line);
$synonyms = array();
// For each synonym line...
while ( $n-- ) {
$line = rtrim(fgets($infile), "\r\n");
$fields = explode('|', $line);
$partOfSpeech = substr(array_shift($fields), 1, -1);
$synonyms[$partOfSpeech] = $fields;
}
// Now here, when $headWord is '**10000', $synonyms should be array(
// 'noun' => array('ten thousand', 'myriad', 'large**')
// )
}
Wow, for this type of functionality you have databases with tables and indices.
PHP is to serve a request/response, not to read a big file into memory. I advise you to put the data in a database. That will be much faster - and it is made for it.