I was wondering how to do it, this code will as you know get specific line, now I need it to read until a specific text like 55 and stops reading from there. As you can see the log contains some whitespace so what function can I use to read until the code 55?
$row['MtID'] = A unique ID to specify the line where the result is.
So for example the log of the result will be
MM3,67624563 (Unique ID (MtID),233262345599,http://mywebsite.com:8080/web/mm3_pixel.php?sspdata=ams1CIv44qa26LGkchACGKqShLrCtZieSyINNDEuMTkwLjg4LjIwOCgB&vurlid=993211,http://mywebsite.net/sspx?id=69171&sspdata=ams1CIv44qa26LGkchACGKqShLrCtZieSyINNDEuMTkwLjg4LjIwOCgB >> OK
,55
$logfile = file("https://myweb.com/Pixel-Full.php?file=".$country."/".$today."-pixel-response.log");
foreach($logfile as $line_num = > $line) {
if (strpos($line, $row['MtID']) !== false) {
$getresult = strstr(htmlspecialchars($line), 'http://');
echo "<td>".$getresult."</td>";
}
}
This system goes like this, a user request something and nothing found, so on our log, it will post the error link requested by user and the error code for us to know what problem it was. So once the system reads the line and continue to read other line as well until it found the code, it stops
$startline = count($logfile)+1;
foreach($logfile as $line_num => $line) {
if (strpos($line, $row['MtID']) !== false) {
$startline = $line_num;
$getresult = trim(strstr(htmlspecialchars($line), 'http://'));
if (strpos($getresult, ",55") !== false) {
$getresult = substr($getresult,0,strpos($getresult, ",55")+3);
break;
}
}
if ($line_num > $startline) {
$getresult .= trim(htmlspecialchars($line));
if (strpos($getresult, ",55") !== false) {
$getresult = substr($getresult,0,strpos($getresult, ",55")+3);
break;
}
}
}
echo "<td>".$getresult."</td>";
You can use the FILE_SKIP_EMPTY_LINES flag in the file call to skip empty lines and then use array_slice to get the part of the array you need.
$file = array_slice(file("https://myweb.com/Pixel-Full.php?file={$country}/{$today}-pixel-response.log", FILE_SKIP_EMPTY_LINES), 0, $row['MtID']);
foreach($file as $line) {
$result = strstr(htmlspecialchars($line), 'http://');
echo "<td>{$result}</td>";
}
It looks like stopping the execution when a positive match is the biggest trick here. This can be done with a break. (http://php.net/manual/en/control-structures.break.php)
//get the file as a string
$logfile = file_get_contents("https://myweb.com/Pixel-Full.php?file=".$country."/".$today."-pixel-response.log", false);
//make up some rows and catch the false
if ($logfile !== false) {
$logrows = explode("\n", $logfile);
//loop
foreach($logrows as $line) {
if (strpos($line, $row['MtID']) !== false) {
$getresult = strstr(htmlspecialchars($line), 'http://');
echo "<td>".$getresult."</td>";
break;
}
}
}
else echo "Log resource unavailable";
//some memory clearing
unset($logfile);
unset($logrows);
I would suggest for matching sanity that you make sure that the logging format makes the MtID variable something that wouldn't be found in the log text unless its a positive match. Using a UUID or a specific ID format would work.
As you regarded, sometimes, the log line may be divided into three lines while in some other times it is only one line:
// Three lines
http://www.yourwebsite.com/error/33/happycodingneverending&errorcode=33,
succcess=false;
,55
// one line
http://www.yourwebsite.com/error/33/happycodingneverending&errorcode=33,succcess=false;,55
In this case you just have to made a little modification to your code, which, works perfect with only one line example to works with that three lines as follows:
foreach($logfile as $line_num = > $line) {
if (strpos($line, $row['MtID']) !== false) {
$getresult = strstr(htmlspecialchars($line), 'http://');
if(!$getresult){
$theExactLine = $line_num - 2;
$getresult = $logfile[$theExactLine];
}
echo "<td>".$getresult."</td>";
break; // to stop looping.
}
}
Related
I've got a piece of code searching a text file for an email address, returning the two numbers on the same line.
The file looks like:
24/08/2017,email#test.ie,1,2
21/05/2018,test#234.com,1,2
21/05/2018,test#test.ie,2,2
My code currently looks like
$lines = file("log.txt");
$found = 0;
foreach ($lines as $line){
if (strpos($line, $email) !==false){
$found = true;
$arrayOfLine = explode(",", $line);
$foundGroup = $arrayOfLine[2];
$foundVideo = $arrayOfLine[3];
}
elseif (strpos($line, $email) ===false){
$found = false;
}
}
When I run this code, through a HTML form that takes in the email address to be searched for, it only finds matching emails if they were the last entered - in my example above, test#234.com wouldn't return a match, but test#test.ie would. What am I missing that's preventing it from turning up matches?
You are not terminating your loop when you find an answer, meaning it continues to run even if it found a match and overwrites any previous match. Add a break; after you assigned $foundGroup and $foundVideo.
You also have two evaluations checking the same thing. Set the $found flag to false at the start of the loop. If your loop fails to find a match, it'll still be false. You don't need to compare twice.
$found = false;
foreach ($lines as $line){
if (strpos($line, $email) !==false){
$found = true;
$arrayOfLine = explode(",", $line);
$foundGroup = $arrayOfLine[2];
$foundVideo = $arrayOfLine[3];
break; // stop searching for more matches
}
}
This is actually pretty easy to figure out.
it only finds matching emails if they were the last entered
This is true. Why? Because you always set $found to false, unless the email address you're searching for is the last one. Even if you have found a match, you're just continuing the loop and overwriting $found with false.
Take a look at this snippet and see if you can figure it out.
You either need to break out of the loop, or stop setting $found this way.
foreach ($lines as $line){
if (strpos($line, $email) !==false) {
$found = true;
$arrayOfLine = explode(",", $line);
$foundGroup = $arrayOfLine[2];
$foundVideo = $arrayOfLine[3];
}
elseif (strpos($line, $email) ===false) {
$found = false; // This will be run every loop!
}
}
I'm getting used to PHP and trying to remove a line from a file (if it exists) and resave the file.
So if I had the file
user1
user2
user3
user4
I could use
if(existsAndRemove("user3")){
do thing
}
I've tried using code similar to the code below but it sometimes bugs out and will only remove a line if it is last in the file. I have no idea how to fix this.
$data2 = file("./ats.txt");
$out2 = array();
foreach($data2 as $line2) {
if(trim($line2) != $acc) {
$out2[] = $line2;
}
}
$fp2 = fopen("./ats.txt", "w+");
flock($fp2, LOCK_EX);
foreach($out2 as $line2) {
fwrite($fp2, $line2);
}
flock($fp2, LOCK_UN);
fclose($fp2);
}
}
Any help at all would be greatly appreciated, and i would also appreciate if you could explain the code too so I could easier learn from it!!
Thank you.
If the file size is small enough that you're not worried about reading it all into memory, you could do something more functional
// Read entire file in as array of strings
$data = file("./ats.txt");
// Some text we want to remove
$acc = 'user3';
// Filter out any lines that match $acc,
// ignoring any leading or trailing whitespace
//
$filtered_data = array_filter(
$data,
function ($line) use ($acc) {
return trim($line) !== $acc;
}
)
// If something changed, write the file back out
if ($filtered_data !== $data) {
file_put_contents('./ats.txt', implode('', $filtered_data));
}
Something like this might work:
function remove_user($user) {
$file_path = "foo.txt"
$users = preg_split("[\n\r]+", file_get_contents($file_path));
foreach ($users as $i => $existing) {
if ($user == $existing) {
$users = array_splice($users, $i, 1);
file_put_contents($file_path, implode("\n", $users));
break;
}
}
}
Should be much easier since you're already using file():
$data2 = file("./ats.txt", FILE_IGNORE_NEW_LINES);
unset($data2[array_search('user3', $data2)]);
file_put_contents("./ats.txt", implode("\n", $data2));
Or to check if it exists first:
$data2 = file("./ats.txt", FILE_IGNORE_NEW_LINES);
if( ($key = array_search('user3', $data2)) !== false ) {
unset($data2[$key]);
file_put_contents("./ats.txt", implode("\n", $data2));
}
I have this textfile:
foo: bar
el: macho
bing: bong
cake color: blue berry
mayo: ello
And I what I'm trying to accomplish is that if I "look" for foo, it returns bar (if I look for bing, it should return bong). A way a tried to accomplish this is first search though the file, return the line with the result, put it in a string and remove everything before the ":" and display the string.
// What to look for
$search = 'bing';
// Read from file
$lines = file('file.txt');
foreach($lines as $line)
{
// Check if the line contains the string we're looking for, and print if it does
if(strpos($line, $search) !== false)
echo $line;
$new_str = substr($line, ($pos = strpos($line, ',')) !== false ? $pos + 1 : 0);
}
echo "<br>";
echo "bing should return bong:";
echo $new_str;
But it doesn't work. Up here is just one of the many things I've tried.
Sources:
Many stackoverflow links on and comparable searches:
https://www.google.com/search?client=opera&q=php+remove+everything+after
https://www.google.com/search?client=opera&q=php+search+text+file+return+line
I've asked a question before, but the answers are to "professional" for me, I really need a noob-proof solution/answer. I've been trying to figure it out all day but I just can't get this to work.
Edit:
It's solved! Thank you so much for your time & help, I hope this might be useful to someone else to!
This should work with what you are looking for, I tested it on my server and it seems to fit what you are looking for.
$lines_array = file("file.txt");
$search_string = "bing";
foreach($lines_array as $line) {
if(strpos($line, $search_string) !== false) {
list(, $new_str) = explode(":", $line);
// If you don't want the space before the word bong, uncomment the following line.
//$new_str = trim($new_str);
}
}
echo $new_str;
?>
I would do it this way:
foreach($lines as $line)
{
// explode the line into an array
$values = explode(':',$line);
// trim the whitspace from the value
if(trim($values[1]) == $search)
{
echo "found value for ".$search.": ".$values[1];
// exit the foreach if we found the needle
break;
}
}
$search = 'bing';
// Read from file
$lines = file('text.txt');
$linea='';
foreach($lines as $line)
{
// Check if the line contains the string we're looking for, and print if it does
if(strpos($line, $search) !== false) {
$liner=explode(': ',$line);
$linea.= $liner[1];
}
}
echo 'Search returned: '. $linea;
Explanation: - $linea var is created before loop, and it will contain search result. If value is found on line - explode string, and make array, get second var from array, put it in search results container variable.
As your data is almost YAML [see lint], you could use a parser in order to get the associated PHP array.
But if can go with your solution as well:
// What to look for
$search = 'bing';
// Read from file
$lines = file('file.txt');
foreach($lines as $line)
{
// Check if the line contains the string we're looking for, and print if it does
if(strpos($line, $search) !== false){
echo array_pop(explode(":", $line));
}
}
Use fgetcsv:
$bits = array();
if (($handle = fopen('t.txt','r')) !== FALSE) {
while (($data = fgetcsv($handle, 0, ":")) !== FALSE) {
$bits[$data[0]] = $data[1];
}
}
# Now, you search
echo $bits['foo'];
$bits will have a key for each split part, which makes your ultimate goal quite simple. Here is what it looks like:
Array
(
[foo] => bar
[el] => macho
[bing] => bong
[cake color] => blue berry
[mayo] => ello
)
I want to record downloads in a text file
Someone comes to my site and downloads something, it will add a new row to the text file if it hasn't already or increment the current one.
I have tried
$filename = 'a.txt';
$lines = file($filename);
$linea = array();
foreach ($lines as $line)
{
$linea[] = explode("|",$line);
}
$linea[0][1] ++;
$a = $linea[0][0] . "|" . $linea[0][1];
file_put_contents($filename, $a);
but it always increments it by more than 1
The text file format is
name|download_count
You're doing your incrementing outside of the for loop, and only accessing the [0]th element so nothing is changing anywhere else.
This should probably look something like:
$filename = 'a.txt';
$lines = file($filename);
// $k = key, $v = value
foreach ($lines as $k=>$v) {
$exploded = explode("|", $v);
// Does this match the site name you're trying to increment?
if ($exploded[0] == "some_name_up_to_you") {
$exploded[1]++;
// To make changes to the source array,
// it must be referenced using the key.
// (If you just change $v, the source won't be updated.)
$lines[$k] = implode("|", $exploded);
}
}
// Write.
file_put_contents($filename, $lines);
You should probably be using a database for this, though. Check out PDO and MYSQL and you'll be on your way to awesomeness.
EDIT
To do what you mentioned in your comments, you can set a boolean flag, and trigger it as you walk through the array. This may warrant a break, too, if you're only looking for one thing:
...
$found = false;
foreach ($lines as $k=>$v) {
$exploded = explode("|", $v);
if ($exploded[0] == "some_name_up_to_you") {
$found = true;
$exploded[1]++;
$lines[$k] = implode("|", $exploded);
break; // ???
}
}
if (!$found) {
$lines[] = "THE_NEW_SITE|1";
}
...
one hand you are using a foreach loop, another hand you are write only the first line into your file after storing it in $a... it's making me confuse what do you have in your .txt file...
Try this below code... hope it will solve your problem...
$filename = 'a.txt';
// get file contents and split it...
$data = explode('|',file_get_contents($filename));
// increment the counting number...
$data[1]++;
// join the contents...
$data = implode('|',$data);
file_put_contents($filename, $data);
Instead of creating your own structure inside a text file, why not just use PHP arrays to keep track? You should also apply proper locking to prevent race conditions:
function recordDownload($download, $counter = 'default')
{
// open lock file and acquire exclusive lock
if (false === ($f = fopen("$counter.lock", "c"))) {
return;
}
flock($f, LOCK_EX);
// read counter data
if (file_exists("$counter.stats")) {
$stats = include "$counter.stats";
} else {
$stats = array();
}
if (isset($stats[$download])) {
$stats[$download]++;
} else {
$stats[$download] = 1;
}
// write back counter data
file_put_contents('counter.txt', '<?php return ' . var_export($stats, true) . '?>');
// release exclusive lock
fclose($f);
}
recordDownload('product1'); // will save in default.stats
recordDownload('product2', 'special'); // will save in special.stats
personally i suggest using a json blob as the content of the text file. then you can read the file into php, decode it (json_decode), manipulate the data, then resave it.
I'm sort of new to PHP, and I need some help on exploding data from a file. The file in question is: http://data.vattastic.com/vatsim-data.txt
Basically, I need to get the data under the !CLIENTS: section (near the bottom). With this data, I need to explode it and get the info between each :.
I have tried with this code, but it gives me a variable offset error (Undefined offset: 3)
$file = file("http://data.vattastic.com/vatsim-data.txt");
foreach($file as $line)
{
$data_record = explode(":", $line);
// grab only the data that has "ATC" in it...
if($data_record[3] == 'ATC' && $data_record[16] != '1' && $data_record[18] != '0'&& stristr($data_record[0],'OBS') === FALSE)
{
rest of code here...
}
}
If someone could help me with this, I'd greatly appreciate it.
This happens because you are trying to explode rows like this:
; !GENERAL contains general settings
When you explode that line, you your $data_records looks like this:
Array (
[0] => ; !GENERAL contains general settings )
Quick solution:
$file = file("http://data.vattastic.com/vatsim-data.txt");
foreach($file as $line)
{
if(strpos($line,';') === 0) continue ; // this is comment. ignoring
$data_record = explode(":", $line);
$col_count = count($data_record);
switch($col_count) {
case 42: // columns qty = 42, so this is row from `clients`
// grab only the data that has "ATC" in it...
if($data_record[3] == 'ATC' && $data_record[16] != '1' && $data_record[18] != '0'&& stristr($data_record[0],'OBS') === FALSE)
{
rest of code here...
}
break;
default:
// this is other kind of data, ignoring
break;
}
}
Another solution is to use regular expressions and look for !CLIENTS: section. This would also work in the case that the CLIENTS have more or less than 42 columns in the future
$file = file_get_contents ("http://data.vattastic.com/vatsim-data.txt");
$matches = null;
preg_match ('/!CLIENTS:\s\n(.*)\n;/s' , $file, $matches );
if($matches)
{
$client_lines = explode("\n", $matches[1]);
foreach ($client_lines as $client)
{
$data_record = explode(":", $client);
if($data_record[3] == 'ATC' && $data_record[16] != '1' && $data_record[18] != '0'&& stristr($data_record[0],'OBS') === FALSE)
{
//rest of code here...
}
}
}