I am having a log file like this :
2013-04-08-03-17-52: Cleaning Up all data for restart operation
2013-04-08-03-18-02: Creating new instance of app before closing
2013-04-08-03-18-03: New instance created and running
2013-04-08-03-18-03: Application started
Currently, i am loading full log file every second to show it to the user using jquery ajax, As this being soo inefficient i am trying to figure out some way to load only the updated lines from log file.
Is their any way to get lines only after a particular time stamp 2013-04-08-03-18-03
, For this i will be managing a variable with last timestamp and will be updating it every time i get new lines.
I am kind of New to Php and know only the basics of reading and writing files.
You might want to check the file modification time first to see whether or not you need to reload the log file. You can use the filemtime-function for that.
Furthermore, you can use the file_get_contents-function using an offset to read the file from a certain point.
Edit: So, how does it work?
Suppose you have stored the last modification time in a session variable $_SESSION['log_lastmod'] and the most recent offset in $_SESSION['log_offset'].
session_start();
// First, check if the variables exist. If not, create them so that the entire log is read.
if (!isset($_SESSION['log_lastmod']) && !isset($_SESSION['log_offset'])) {
$_SESSION['log_lastmod'] = 0;
$_SESSION['log_offset'] = 0;
}
if (filemtime('log.txt') > $_SESSION['log_lastmod']) {
// read file from offset
$newcontent = file_get_contents('log.txt', NULL, NULL, $_SESSION['log_offset']);
// set new offset (add newly read characters to last offset)
$_SESSION['log_offset'] += strlen($newcontent);
// set new lastmod-time
$_SESSION['log_lastmod'] = filemtime('log.txt');
// manipulate $newcontent here to what you want it to show
} else {
// put whatever should be returned to the client if there are no updates here
}
You can try
session_start();
if (! isset($_SESSION['log'])) {
$log = new stdClass();
$log->timestamp = "2013-04-08-03-18-03";
$log->position = 0;
$log->max = 2;
$_SESSION['log'] = &$log;
} else {
$log = &$_SESSION['log'];
}
$format = "Y-m-d-:g:i:s";
$filename = "log.txt";
// Get last date
$dateLast = DateTime::createFromFormat($format, $log->timestamp);
$fp = fopen($filename, "r");
fseek($fp, $log->position); // prevent loading all file to memory
$output = array();
$i = 0;
while ( $i < $log->max && ! feof($fp) ) {
$content = fgets($fp);
// Check if date is current
if (DateTime::createFromFormat($format, $log->timestamp) < $dateLast)
continue;
$log->position = ftell($fp); // save current position
$log->timestamp = strstr($content, ":", true); // save curren time;
$output[] = $content;
$i ++;
}
fclose($fp);
echo json_encode($output); // send to ajax
Try something like this:
<?php
session_start();
$lines = file(/*Insert logfile path here*/);
if(isset($_SESSION["last_date_stamp"])){
$new_lines = array();
foreach($lines as $line){
// If the date stamp is newer than the session variable, add it to $new_lines
}
$returnLines = array_reverse($newLines); // the reverse is to put the lines in the right order
} else {
$returnLines = $lines;
}
$_SESSION['last_date_stamp'] = /* Insert the most recent date stamp here */;
// return the $returnLines variable
?>
What this does is reads a file line by line and, if a session variable already exists, add all of the lines where the date stamp is newer than the one in the session variable to a return variable $returnLines, if no session variable exists it will put all of the lines in the file in $returnLines.
After this, it create.updates the session variable for use the next time the code is executed. Finally it returns the log file data by using the $returnLines variable.
Hope this helps.
Related
I have a php function that reads a line (random message) from a file and displays it on my web page. It displays a new message every time I click refresh, but I want it to display the message for a day (it should change at midnight). Is it possible to do it with another function, implying my database? Or with a JS function?
EDIT
This is the function (not my code):
function loadMessagesFromFile()
{
$path = ROOT_PATH. '/messages.txt';
$file = fopen($path,"r");
$messages = array();
while($data = fgets($file))
{
$messages[] = $data;
}
fclose($file);
return $messages;
}
This is how I use it to display the message:
$messages_from_file = loadMessagesFromFile();
$key = array_rand($messages_from_file);
$full_text = $messages_from_file[$key];
LATER EDIT
I found the answer here: <https://stackoverflow.com/questions/6815614/generating-word-of-the-day-via-php-random-number#:~:text=Just%20set%20the%20current%20date,same%20number%20for%20one%20Day.>
You have multiple possibilities:
Create a file with only one line every day taken from the other file
Create a cron who will be executed ad midnight who will get a random message and set it in database or cache.
If you want a different message per people but persist one day, you can use the local storage of the visitor to store the message with the current date and if the date stored is different from the current date, you change it.
get total lines from your file
Use a database or file and store a random number daily.
Use that number to read a random message from the file.
Use cron to update random numbers at midnight in your database or file.
So, for 24 hours the same message will be displayed.
function getRandomNo(): int {
$path = ROOT_PATH. '/randomno.txt';
$file = fopen($path,"r");
$data = fread($file,100);
fclose($file);
if($data) {
$parts = explode('=',$data);
if($parts[0] != date("Y-m-d")) {
$randomNo = rand(0,100);
overWrite($randomNo);
} else {
$randomNo = $parts[1];
}
} else {
$randomNo = rand(0,100);
overWrite($randomNo);
}
return $randomNo;
}
function overWrite(int $randomNo): void {
$path = ROOT_PATH. '/randomno.txt';
$file = fopen($path,"w+");
$data = date("Y-m-d").'='.$randomNo;
fwrite($file, $data);
fclose($file);
}
$messages_from_file = loadMessagesFromFile();
$key = getRandomNo();
$full_text = $messages_from_file[$key];
I have no luck when the subject is reading text files. I have a small script to read a log file (real time updated) but I want to send some data to DB.
And the problem is, if I don't stat reading from the end of the files, I will get duplicated entries in database. Wich can't happen!
// Keep alive
for (;;)
{
$handle = fopen("data.log", "r");
if (!$handle) die("Open error - data.log");
while (!feof($handle))
{
$line = fgets($handle, 4096);
// If match with, I output the result
if (strpos($line, ':gshop_trade:') > 0)
{
if (!preg_match('/([\d-: ]+)\s*.*\sformatlog:gshop_trade:userid=(\d+):(.*)item_id=(\d+):expire=(\d+):item_count=(\d+):cash_need=(\d+):cash_left=(\d+).*$/', $line, $data))
{
echo "Parsing error on line: {$line}";
}
// show the data
}
}
sleep(5);
}
This script is working, but as I mentioned above, I need to send the data to BD. But also, I need to leave script running, with this current code, the script match the wanted string, and instead of wait for new entries on data.log he starting reading the whole file again.
I see this question here and I tested but doesn't work. I'll start the script when I start the service that generates "data.log" but to prevent duplicate entries in database, I need to read the last lines.
How can I do that?
Keep a track of the file offset from the previous reading using ftell() and keeping that result in a variable, and jump to that offset in the file when you re-open it for the next reading using fseek()
$lastPos = 0;
for (;;)
{
$handle = fopen("data.log", "r");
if (!$handle) die("Open error - data.log");
fseek($handle, $lastPos); // <--- jump to last read position
while (!feof($handle))
{
$line = fgets($handle, 4096);
$lastPos = ftell($handle); // <--- maintain last read position
// If match with, I output the result
if (strpos($line, ':gshop_trade:') > 0)
{
if (!preg_match('/([\d-: ]+)\s*.*\sformatlog:gshop_trade:userid=(\d+):(.*)item_id=(\d+):expire=(\d+):item_count=(\d+):cash_need=(\d+):cash_left=(\d+).*$/', $line, $data))
{
echo "Parsing error on line: {$line}";
}
// show the data
}
}
sleep(5);
}
Maybe you can use file_get_contents, explode and read the array backwards?
$arr = explode(PHP_EOL, file_get_contents("data.log")); // or file("data.log");
$arr = array_reverse($arr);
foreach($arr as $line){
// do stuff here in reverse order
}
From comments above I suggest this method to only use the new data in your code.
It will read your log and a text file with what has been read last time.
Remove what was read last time and use the new data in the code.
$logfile = file_get_contents("data.log");
$ReadData = file_get_contents("readdata.txt");
$newdata = str_replace($ReadData, "", $logfile); // this is what is new since last run.
file_put_contents("readdata.txt", $logfile); // save what has been read.
$arr = explode(PHP_EOL, $newdata);
foreach($arr as $line){
// do your stuff here with the new data.
}
?>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="refresh" content="5"> <!-- This will run the page every five seconds.
</head>
</html>
I want to get the page count in my index page,using cookie.So far I have done like.Now My question is:If I refresh the page, The browser shows with count 2 and it doesnot increase for next refresh.I don't know what is wrong in my code.Further I want to know how to handle cookie in next page or shall I can handle cookie in same page? can any one guide please.but this is my requirement.
<?php
$cookie = 1;
setcookie("count", $cookie);
if (!isset($_COOKIE['count']))
{
}
else
{
$cookie = ++$_COOKIE['count'];
}
echo "The Total visit is".$cookie;
?>
I decided to use local storage for this as I really dislike cookies, some users block them completely.
You can setup the echo. To work with this
Here is what I cam up with: http://jsfiddle.net/azrmno86/
// Check browser support
if (typeof(Storage) != "undefined") {
//check if the user already has visited
if (localStorage.getItem("count") === "undefined") {
//set the first time if it dfoes not exisit yet
localStorage.setItem("count", "1");
}
//get current count
var count = localStorage.getItem("count");
//increment count by 1
count++;
//set new value to storage
localStorage.setItem("count", count);
//display value
document.getElementById("result").innerHTML = count
} else {
document.getElementById("result").innerHTML = "Sorry, your browser does not support";
}
UPDATE After a bit more clarification
This style uses a .txt file stored on the server. Cookies are not reliable. If someone clears them, your done. if you use variables any server restart will kill your count. Eith use database or this method.
<?php
//very important
session_start();
$counter_name = "counter.txt";
// Check if a text file exists. If not create one and initialize it to zero.
if (!file_exists($counter_name)) {
$f = fopen($counter_name, "w");
fwrite($f,"0");
fclose($f);
}
// Read the current value of our counter file
$f = fopen($counter_name,"r");
$counterVal = fread($f, filesize($counter_name));
fclose($f);
// Has visitor been counted in this session?
// If not, increase counter value by one
if(!isset($_SESSION['hasVisited'])){
$_SESSION['hasVisited']="yes";
$counterVal++;
$f = fopen($counter_name, "w");
fwrite($f, $counterVal);
fclose($f);
}
echo "You are visitor number $counterVal to this site";
Hopefully, I won't be a novice for long. I have a 2-dimensional array (simplified) that I'm trying to work with. Simply pulling out, adding to, and uploading a file record. Can somebody forgive my ignorance and explain what I'm doing wrong?:
<?php
// Updating Current Number of Vendors
$vendorcount = #file_get_contents('../Keys/VendorCount/$v');
if(isset($vendorcount))
{
$new_vendor_number = ($vendorcount + 1);
$n = $new_vendor_number;
}
else
{
$vendorcount = 0;
$new_vendor_number = 1;
$file = '../Keys/VendorCount/$v' ;
file_put_contents($file, $vendorcount) ;
};
//getting record from file
$record = file_get_contents('../Vendors/$vendorlist');
//adding new information to record array
$record[$n] = array($new_vendor_number, $catname);
//uploading updated record
$file = '../Vendors/$vendorlist' ;
file_put_contents($file, $record) ;
?>
You need to use serialize() and unserialize() in order to store an array to a file or restore it from a file. Like this:
$array = array(1,2,3);
// writing to file
file_put_contents('file.txt', serialize($array));
// restoring from file
$array = unserialize(file_get_contents('file.txt'));
This will work with arrays of any dimension.
Is there any alternative to file_get_contents that would create the file if it did not exist. I am basically looking for a one line command. I am using it to count download stats for a program. I use this PHP code in the pre-download page:
Download #: <?php $hits = file_get_contents("downloads.txt"); echo $hits; ?>
and then in the download page, I have this.
<?php
function countdownload($filename) {
if (file_exists($filename)) {
$count = file_get_contents($filename);
$handle = fopen($filename, "w") or die("can't open file");
$count = $count + 1;
} else {
$handle = fopen($filename, "w") or die("can't open file");
$count = 0;
}
fwrite($handle, $count);
fclose($handle);
}
$DownloadName = 'SRO.exe';
$Version = '1';
$NameVersion = $DownloadName . $Version;
$Cookie = isset($_COOKIE[str_replace('.', '_', $NameVersion)]);
if (!$Cookie) {
countdownload("unqiue_downloads.txt");
countdownload("unique_total_downloads.txt");
} else {
countdownload("downloads.txt");
countdownload("total_download.txt");
}
echo '<META HTTP-EQUIV=Refresh CONTENT="0; URL='.$DownloadName.'" />';
?>
Naturally though, the user accesses the pre-download page first, so its not created yet. I do not want to add any functions to the pre download page, i want it to be plain and simple and not alot of adding/changing.
Edit:
Something like this would work, but its not working for me?
$count = (file_exists($filename))? file_get_contents($filename) : 0; echo $count;
Download #: <?php
$hits = '';
$filename = "downloads.txt";
if (file_exists($filename)) {
$hits = file_get_contents($filename);
} else {
file_put_contents($filename, '');
}
echo $hits;
?>
you can also use fopen() with 'w+' mode:
Download #: <?php
$hits = 0;
$filename = "downloads.txt";
$h = fopen($filename,'w+');
if (file_exists($filename)) {
$hits = intval(fread($h, filesize($filename)));
}
fclose($h);
echo $hits;
?>
Type juggling like this can lead to crazy, unforeseen problems later. to turn a string to an integer, you can just add the integer 0 to any string.
For example:
$f = file_get_contents('file.php');
$f = $f + 0;
echo is_int($f); //will return 1 for true
however, i second the use of a database instead of a text file for this. there's a few ways to go about it. one way is to insert a unique string into a table called 'download_count' every time someone downloads the file. the query is as easy as "insert into download_count $randomValue" - make sure the index is unique. then, just count the number of rows in this table when you need the count. the number of rows is the download count. and you have a real integer instead of a string pretending to be an integer. or make a field in your 'download file' table that has a download count integer. each file should be in a database with an id anyway. when someone downloads the file, pull that number from the database in your download function, put it into a variable, increment, update table and show it on the client however you want. use PHP with jQuery Ajax to update it asynchronously to make it cool.
i would still use php and jquery.load(file.php) if you insist on using a text file. that way, you can use your text file for storing any kind of data and just load the specific part of the text file using context selectors. the file.php accepts the $_GET request, loads the right portion of the file and reads the number stored in the file. it then increments the number stored in the file, updates the file and sends data back to the client to be displayed any way you want. for example, you can have a div in your text file with an id set to 'downloadcount' and a div with an id for any other data you want to store in this file. when you load file.php, you just send div#download_count along with the filename and it will only load the value stored in that div. this is a killer way to use php and jquery for cool and easy Ajax/data driven apps. not to turn this into a jquery thread, but this is as simple as it gets.
You can use more concise equivalent yours function countdownload:
function countdownload($filename) {
if (file_exists($filename)) {
file_put_contents($filename, 0);
} else {
file_put_contents($filename, file_get_contents($filename) + 1);
}
}