I have function build_additional_docs which calls another function that do few actions, but first it's call to function read_all_file, which extract the file to string variable and return it.
It's worked perfect when the function create_file_node has been called from another function.
but when it's called from build_additional_docs, the client wait to server untill time out...
I think that the function fail on fgets().
Additional comment: When I call function create_file_node whith with the same files, and the different is that file name is static string, and I have no foreach loop, the code works again...
here is my code:
function build_additional_docs($dir_name, $addDocsArr){
foreach ($addDocsArr as $doc) {
if($summery != ''){
$fileName = $dir_name . '\\' . $doc;
create_file_node($fileName);
}
}
function create_file_node($fileName){ global $base_url;
try{
$text = read_all_file($fileName);
}
catch (Exception $ex){
// some message here
}
return 0;
}
function read_all_file($file_name){
$file_handle = fopen($file_name, "r");
while (!feof($file_handle)) {
$line[] = fgets($file_handle);
}
fclose($file_handle);
return implode('',$line);
}
Found the mistake!
$addDocsArr variable is return value from explode() function for split string to seperated files names. The returned array include strings of file name with spacial characters that cannot be seen...
so when i add the code:
$fileName = $dir_name . '\\' . substr($doc, 0,strlen($doc) - 1);
the code worked.
Related
I am trying to record hits to my website to a text file and I want to limit the size of the text file to some value. Once the limit is crossed I want a new file to be created dynamically. With my current code, a new file does get created after the set limit is passed, but the rest of the data is only stored on that new file.
public function storeActivityHitCount(Request $request)
{
if($request->ajax() && isset($request->data)){
$clientIP = request()->ip(); $i= 1;
$date = date("Y-m-d h:i:sa");
$data = $clientIP.', '.$date.', '.$request->data;
$file = public_path().'/adminpanel/hits/activity/activity'.$i.'.txt';
if(!file_exists($file)){
fopen($file,"w+");
}
$filesize = filesize($file);
if($filesize >= 76){ $i++;
$file1 = public_path().'/adminpanel/hits/activity/activity'.$i.'.txt';
if(!file_exists($file1)){
fopen($file1,"w+");
}
$content = file_get_contents($file1);
$content .= $data. PHP_EOL;
$upload_success = file_put_contents($file1, $content);
}else{
$content = file_get_contents($file);
$content .= $data. PHP_EOL;
$upload_success = file_put_contents($file, $content);
}
if($upload_success){
return Response::json(['status' => 'success'], 200);
}
return Response::json(['status' => 'failed'], 400);
}
abort(403);
}
Your original code of course was only trying one other file and then writing to it regardless of its size. You want to put that logic into a repeating structure. Or in other words, you want to look for a different file while you keep finding full ones.
public function storeActivityHitCount(Request $request)
{
if ($request->ajax() && isset($request->data)) {
$clientIP = request()->ip();
$date = date('Y-m-d h:i:sa');
$data = $clientIP . ', ' . $date . ', ' . $request->data;
$i = 1;
$file = public_path() . '/adminpanel/hits/activity/activity' . $i . '.txt';
while (filesize($file) >= 76 && $i <= 20) {
$i++;
$file = public_path() . '/adminpanel/hits/activity/activity' . $i . '.txt';
}
if (filesize($file) >= 76) {
// the loop got away from us
// do something?
$upload_success = false;
} else {
$upload_success = file_put_contents($file, $content, \FILE_APPEND);
}
if ($upload_success) {
return Response::json(['status' => 'success'], 200);
}
return Response::json(['status' => 'failed'], 400);
}
abort(403);
}
I put an upper limit of 20 iterations on the loop; you usually don't want a while loop without some kind of escape mechanism.
file_put_contents will always create a file that doesn't exist, so you didn't need to use fopen (and, you weren't using fclose.) Furthermore, if you pass the FILE_APPEND flag, it will append to the existing file; no need for getting contents and appending stuff to it.
Try to keep your code consistent and readable. Multiple commands on one line, inconsistent whitespace around control structures and operators, inconsistent indentation: all these things end up making you work harder than you have to.
And, of course, this would all be better handled by standard system tools like logrotate which is probably running on your server.
I would isolate the action of getting the activity log file. Like using a function like this:
function getAvailableActivityLogFile(){
$looking=true;
$i=0;
while($looking){
$i++;
$file_path = public_path() . "/adminpanel/hits/activity/activity{$i}.txt";
// If file does not exist or file is less than 76bytes you have the right candiate
if(!file_exists($file_path) || filesize($file_path) < 76){
$looking=false;
return fopen($file_path, 'a+');
}
// Otherwise keep looking on next iteration. You can also write some logic to have a max of loop iterations or max files to look for also.
}
}
Then you can use this function to get the next available file and don't bother with too much logic about what file is available. In my version about you should use fwrite() to write to the file using the file pointer returned by the function.
With the a+ option, you get a pointer there that appends content to the file on every new fwrite to the pointer.
You can also write the function to retrieve a path instead of a pointer.
first sorry for my english
I have array will used by function
Upload text file and every line will be element in array
$fh = fopen("upload/".'1.txt','r');
$conn = array();
while ($line = fgets($fh)) {
$conn[] = $line;
}
fclose($fh);
$wbs->SendBulk($conn, "hello world");
Go To Function
public function SendBulk($targets, $message)
{
echo "Sending " . count($targets) . " bulk messages...<br />";
foreach($targets as $target)
{
$this->wa->sendPresenceSubscription($target);
$this->wa->pollMessages();
$this->wa->sendMessageComposing($target);
sleep(55);
$this->wa->pollMessages();
$this->wa->sendMessagePaused($target);
static::$sendLock = true;
echo "Sending message from " . $this->username . " to $target... ";
$this->wa->sendMessage($target, $message); // Orginal
while(static::$sendLock)
{
//wait for server receipt
sleep(55);
}
}
My Problem If I have in text file 2 or more element in array
will send for the last element a message
but If i make array like this
$conn= array("565684898", "484849815", "484897987", "515498798");
It work for all elements
Please Help
The string returned by fgets() includes the newline that ends each line. Use rtrim() to remove it:
$conn[] = rtrim($line);
You can also replace your entire code that reads the file with:
$conn = file('upload/1.txt', FILE_IGNORE_NEW_LINES)
I've been working o this for the last few weeks and can't find an alternate route. What I need to do is return the contents of a text file after the file has been read. I have two different logs that use text files to log errors. The first log returns the correct variable that I ask for but for some reason, even though I use the exact same methods to call the variable, it doesn't return anything. If I echo the variable then the correct string is displayed but the variable returns nothing. Here is the function:
function GetNoticeLog($strDate){
$logdate = preg_replace("/[^0-9]/", "_", $strDate );
$strFileName = realpath('debuglogs/enotice_logs').'/ENOTICELOG_' . $logdate . '.txt';
if(is_readable($strFileName)){
$file = fopen($strFileName,"r");
$contents = fread($file, filesize($strFileName));
$fclose($file);
return nl2br($contents);
}
else if(!is_readable($strFileName)){
echo $strFileName." is unreadable";
}
}
Why does this function return the necessary string when executed in one function but has to be echoed to see content in the other is my question.
Try changing
$fclose($file);
to this
fclose($file);
I was able to get the code to work on my server. The only change I made here is the path to the file which is in the same directory as the PHP script.
<?php
function GetNoticeLog($strDate){
$logdate = preg_replace("/[^0-9]/", "_", $strDate );
//$strFileName = realpath('debuglogs/enotice_logs').'/ENOTICELOG_' . $logdate . '.txt';
$strFileName = "blah.txt";
if(is_readable($strFileName)){
$file = fopen($strFileName,"r");
$contents = fread($file, filesize($strFileName));
fclose($file);
return nl2br($contents);
}
else if(!is_readable($strFileName)){
echo $strFileName." is unreadable";
}
}
$stuff = GetNoticeLog("whatever");
echo $stuff;
?>
I sense that I am almost there.
Here is a .txt file, which is about 60 Kbytes and full of German words. Every word is on a new line.
I want to iterate through it with this code:
<?php
$file = "GermanWords.txt";
$f = fopen($file,"r");
$parts = explode("\n", $f);
foreach ($parts as &$v)
{
echo $v;
}
?>
When I execute this code, I get: Resourceid#2
The word resource is not in the .txt, I do not know where it comes from.
How can I manage to show up all words in the txt?
No need for fopen just use file_get_contents:
$file = "GermanWords.txt";
$contents = file_get_contents($file);
$lines = explode("\n", $contents); // this is your array of words
foreach($lines as $word) {
echo $word;
}
fopen() just opens the file, it doesn't read it -- In your code, $f contains a file handle, not the file contents. This is where the word "Resource" comes from; it's PHP's internal name for the file handle.
One answer would be to replace fopen() with file_get_contents(). This opens and reads the file in one action. This would solve the problem, but if the file is big, you probably don't want to read the whole thing into memory in one go.
So I would suggest instead using SplFileObject(). The code would look like this:
<?php
$file = "GermanWords.txt";
$parts = new SplFileObject($file);
foreach ($parts as $line) {
echo $line;
}
?>
It only reads into memory one line at at time, so you don't have to worry about the size of the file.
Hope that helps.
See the PHP manual for more info: http://php.net/manual/en/splfileobject.construct.php
$f, the result of fopen is a resource, not the contents of the file. If you just want an array of the lines contained in the file, you can use file:
$parts = file('GermanWords.txt');
foreach($parts as $v){
echo $v;
}
Alternatively, if you want to stick with fopen you can use fread to read the content:
$f = fopen('GermanWords.txt', 'r');
// read the entire file into $contents
$contents = fread($f, filesize('GermanWords.txt'));
fclose($handle);
$parts = explode("\n", $contents);
The SplFileObject provides a way to do that :
$file = new SplFileObject("file.txt");
while (!$file->eof()) {
echo $file->fgets();
}
And if you prefer the foreach loop, you can create a generator function for that :
function lines($filename) {
$file = new SplFileObject($filename);
while (!$file->eof()) {
yield $file->fgets();
}
}
foreach (lines('German.txt') as $line) {
echo $line;
}
Reading the entire content of the file (with file_get_contents) before treating it can be memory consuming.
If you want to treat a file line by line, this class might help you.
It implements an Iterator (see phpdoc about it), that can be walked through in a foreach loop. Only the last line read is stored in memory.
class TxtFileIterator implements \Iterator{
protected $fileHandler;
protected $key;
protected $current;
protected $fileName;
function __construct($fileName){
$this->fileHandler = fopen($fileName, "r") or die("Unable to open file!");
$this->fileName = $fileName;
$this->key = 0;
}
function __destruct(){
fclose( $this->fileHandler );
}
//Iterator interface
public function current (){
return $this->current;
}
public function key (){
return $this->key;
}
public function next (){
if ( $this->valid() ){
$this->current = fgets( $this->fileHandler );
$this->key++;
}
}
public function rewind (){
$this->__destruct();
$this->__construct( $this->fileName );
}
public function valid (){
return !feof( $this->fileHandler );
}
Usage :
$iterator = new TxtFileIterator("German.txt");
foreach ($iterator as $line) {
echo $line;// or do whatever you want with line
}
I use this often and would like to turn it into a function:
$f = fopen('../images/snotel/'. $name .'.pdf','w+');
fwrite($f, $pdf);
fclose($f);
$conv='/usr/bin/convert../images/snotel/'. $name .'.pdf ../images/snotel/'. $name .'.jpg';
system ($conv);
This is what I've tried but it doesn't seem to work:
function pdf2jpg($name)
{
$f = fopen('../images/snotel/'. $name .'.pdf','w+');
fwrite($f, $pdf);
fclose($f);
$conv='/usr/bin/convert../images/snotel/'. $name .'.pdf ../images/snotel/'. $name .'.jpg';
system ($conv);
}
...
pdf2jpg('wsr');
As it is, your function tries to write the file with no data in the $pdf variable, because you did not pass it in.
You need to do one of two things:
This version takes the PDF data as an argument and creates the file in the function:
function pdf2jpg ($pdf, $name) {
$f = fopen('../images/snotel/'.$name.'.pdf','w');
fwrite($f,$pdf);
fclose($f);
$conv = '/usr/bin/convert ../images/snotel/'.$name.'.pdf ../images/snotel/'.$name.'.jpg';
//run
system($conv);
}
// Usage
pdf2jpg($pdf, 'wsr');
This version just takes the name, assuming that the file already exists:
function pdf2jpg ($name) {
$conv = '/usr/bin/convert ../images/snotel/'.$name.'.pdf ../images/snotel/'.$name.'.jpg';
//run
system ($conv);
}
// Usage
$name = 'wsr';
$f = fopen('../images/snotel/'.$name.'.pdf','w');
fwrite($f,$pdf);
fclose($f);
pdf2jpg($name);