So, say you have a php post script that appends whatever you pass to it to a text file as a new line
Let say the file is called file.txt and looks like this:
11:45 Am
12:49 PM
Went to Lunch
3:25 PM
I wanna know, how can I write a php script that treats information as pairs of 3.
so in a for loop it would display
line1 | line2 | line3
line4
Notice that there is nothing past line4, so it stopped.
You can use (demo)
$chunksOfThree = array_chunk(file('/path/to/file', FILE_IGNORE_NEW_LINES), 3);
foreach ($chunksOfThree as $chunk) {
echo implode(' | ', $chunk), PHP_EOL;
}
This will output the desired
11:45 Am | 12:49 PM | Went to Lunch
3:25 PM
See the Manual entries for
file — Reads entire file into an array and
array_chunk — Split an array into chunks
implode — Join array elements with a string
fgets reads an entire line from the file. It is slower than something like fread but does what you want.
You can also use the file function to read the whole file into an array. Each element in the array corresponds to a line in the file.
If the number of lines read is not a multiple of 3, just ignore the last 1 or 2 lines.
fgets returns false if there is no more data so you can check that to determine if one of the triplet entries is incomplete.
while(!feof($fp)) {
$line1 = fgets($fp);
$line2 = fgets($fp);
$line3 = fgets($fp);
if ($line2 === false) {
echo "$line1";
} else if ($line3 == false) {
echo "$line1 | $line2";
} else {
echo "$line1 | $line2 | $line3\n";
}
You can use this code for this
<?php
$filename = "test.txt";
$fp = fopen( $filename, "r" ) or die("Couldn't open $filename");
$i=0;
while ( ! feof( $fp ) ) {
$line = fgets( $fp, 1024 );
if($i==2)
{
print "$line";
$i=0;
print "<br>";
}
else
{
print "$line | ";
$i++;
}
}
?>
Output :
11:45 Am | 12:49 PM | Went to Lunch
3:25 PM |
Related
I have a text file like this:
1
2
3
4
5
6
7
8
9
10
And I want to remove specific lines which numbers are in an array like this:
$myfile='txt.txt';
$remove=array(1,3,6,7,10);
//wanna remove these lines
So I tried this code but It didn't work and It just doubles the text and ruins everything:
<?php
$myfile='txt.txt';
$remove=array(1,3,5,7,10);
$lines=file($myfile);
$countline=sizeof($lines);
$data=file_get_contents($myfile);
for ($i=0; $i < $countline+1; $i++) {
if (in_array($i, $remove)) {
$editeddata=str_replace($lines[$i], "", $data);
$removeline = file_put_contents($myfile, $editeddata.PHP_EOL , FILE_APPEND | LOCK_EX);
}
}
?>
I couldn't use ((for)) properly and I think it will just ruin the text because it deletes lines one after another have been deleted and it changes the order so I should have a code to remove them all at once.
And please don't give a code to just replace numbers because the main text file is not only numbers and contains word,etc...
Thanks A lot!
You're reading the file twice (with file and file_get_contents), which I think is confusing the later code. You have everything you need with the first call - an array of all the lines in the file. You're also using str_replace to remove the content, which seems a bit dangerous if any of the content is repeated.
I'd refactor this to simply filter the array of lines based on their line-number, then write it back to the file in a single operation:
$myfile = 'txt.txt';
$remove = [1, 3, 5, 7, 10];
// Read file into memory
$lines = file($myfile);
// Filter lines based on line number (+1 because the array is zero-indexed)
$lines = array_filter($lines, function($lineNumber) use ($remove) {
return !in_array($lineNumber + 1, $remove);
}, ARRAY_FILTER_USE_KEY);
// Re-assemble the output (the lines already have a line-break at the end)
$output = implode('', $lines);
// Write back to file
file_put_contents($myfile, $output);
If the file fits in memory then you can do the simple:
$myfile='txt.txt';
$remove=array(1,3,6,7,10);
file_put_contents($myfile, implode(PHP_EOL,array_diff($file($myfile,FILE_IGNORE_NEW_LINES), $remove)));
Note: Because it's a bit ambiguous whether $remove has the content or the lines you want to remove, the above code removes the content . If you want to remove lines change array_diff($file($myfile,FILE_IGNORE_NEW_LINES), $remove) to array_diff_keys($file($myfile,FILE_IGNORE_NEW_LINES), array_flip($remove))
If your file is large then you need to resort to some sort of streaming. I suggest against reading and writing to the same file and doing something like:
$myfile='txt.txt';
$remove=array(1,3,6,7,10);
$h = fopen($myfile,"r");
$tmp = fopen($myfile.".tmp", "w");
while (($line = fgets($h)) !== false) {
if (!in_array(rtrim($line, PHP_EOL), $remove)) {
fwrite($tmp, $line);
}
}
fclose($h);
fclose($tmp);
unlink($myfile);
rename($myfile.".tmp", $myfile);
Irrelevant context: running a php script to get a file transferred from one db to another, basically.
My code:
1 $urlVar = "http://www.website.com/api/file_service.php?action=download&companyID=1234&pass=4321&videoID=123456";
2 $file = file_get_contents($urlVar);
3 if ($handle = fopen($urlVar, 'r')) {
4 $stream = stream_get_contents($handle, -1, 0);
5 fclose($handle);
6 }
7
8 $output = date("F j, Y, g:i:s a") . "\n\n";
9 $output .= $urlVar . "\n";
10 $output .= $file . "\n\n\n\n";
11 $output .= $stream . "\n";
12 file_put_contents('file.txt', $output . "\n");
Output (I've typed in the line numbers myself. They aren't actually in the file):
1 6e65 2037 2c20 3230 3138 2c20 323a 4a75
2 3831 3230 2663 6f6d 7061 6e79 5061 7373
3 3020 2d20 6874 7470 3a2f 2f77 7777 2e76
...
43129 0000 0000 0000 0000 002b 696c 7374 0000
43130 0001 0000 0000 4c61 7666 3532 2e39 332e
43131 300a 0a
Note: in the file, I don't see any line breaks. I assumed that putting 4 \n's would show up, but they don't. Is my file getting turned into solely hex??
Output if lines 10 and 11 are commented:
1 June 7, 2018, 1:56:00 pm
2
3 http://www.website.com/api/file_service.php?action=download&companyID=1234&pass=4321&videoID=123456
If I understand it correctly, you want to download the remote output with file_get_contents and then store it in a local file?
Then it's simple
$urlVar = "http://www.website.com/api/file_service.php?action=download&companyID=1234&pass=4321&videoID=123456";
$file = file_get_contents($urlVar);
//check not FALSE
if ($file) {
$handle = fopen('localfile.txt', 'w');
//if you append the date before you will break the file
//in the case it's not a normal text file you will need when reading
//a code that skips the first line
fwrite($handle, date("F j, Y, g:i:s a")."\n\n");
//better to avoid it and just put the timestamp in db or in filename------
fwrite($handle, $file);
fclose($handle);
}
If file_get_contents fails then it's php.ini fault, change allow_url_fopen to On
file: data.txt (11617 lines)
user datetime
23 2015-03-01 08:04:15
15 2015-05-01 08:05:20
105 2015-05-01 08:07:10
15 2015-06-01 08:08:29
105 2015-06-01 08:12:48
I only need data in 2015-06, I'm using fget and check each line's datetime but really slow, more than 50s.
$d='data.txt';
import($d);
function import($d){
$handle = fopen($d, "r") or die("Couldn't get handle");
if ($handle) {
while (!feof($handle)) {
$buffer = fgets($handle, 4096);
$line=explode("\t",$buffer);
if(date("Y-m",strtotime($line[1])=="2015-06"){
mysql_query("INSERT INTO `table` ....");
}
else{
//break? when month>6
}
}
fclose($handle);
}
}
SOLUTION: less than 2s!!!! (thanks to Kevin P. and Dragon)
if(substr($line[1],0,7)=="2015-06"){
$sql.=empty($sql)?"":","."(`".$line[1]."`.........)";
}
elseif(substr($line[1],0,7)>"2015-06"){
break;// when month>6
}
mysql_query("INSERT INTO `table` ....".$sql);
Can't be helped, use something faster than PHP. For instance, you can use grep or awk to read the file and filter it quickly. For example:
$lines = explode("\n", `awk '$2 ~ /^2015-06/ { print }' data.txt`);
EDIT: Also, fgets is not guaranteed to give you whole lines. You are getting 4096 bytes at a time; the boundary could be in the middle of a line, which will make the line not match if you are lucky, or break your code due to missed assumptions (such as the length of the $line array when constructing the SQL) if not.*
*) Or vice versa - it would be better for it to break completely, that is at least an obvious error yelling to be fixed; as opposed to silent data droppage.
Maybe insert multiple entries in to the DB at once instead of calling it every time you find a desired time?
In which case it's similar to this
Maybe you should use grep to filter out the lines you do not need.
I have used a while loop to fetch rows from a database and collect them in an array.
Now what I want to achieve is that on each iteration of this loop, the elements of the array should be written on a new line in a text file
I've tried implode but it's not working. I am probably using it in a completely wrong way.
Here is my code:
$query = "SELECT hist FROM loch ;";
$result = mysql_query($query) or die(mysql_error());
$file = "/opt/lampp/htdocs/rrugd/ip.txt";
fopen($file,'a');
$output=array();
while($row=mysql_fetch_row($result))
{
$instr1 = implode("\n", $row);
file_put_contents($file, $instr1, FILE_APPEND | LOCK_EX);
}
I want the output to look like this -
1 2 10 5
1 2 10
But what I am getting is this -
1 2 10 51 2 10
Where am I going wrong?
Use PHP_EOL to add a new line like so:
file_put_contents($file, $instr1 . PHP_EOL, FILE_APPEND | LOCK_EX);
I am using php to grab a shell output that lists all the meetme channels for me. I just want to grab the Conf Num that has 0001 from the bottom up. In my example below, I would like to assign variable: $confnum="32";
Here is my code so far:
$output = shell_exec("asterisk -rx 'meetme list'");
echo $output;
Please help me take the results from $output.
Here's what you'll get when executing the meet.php file
[root#C1033-TF agi-bin]# php meet.php
Conf Num Parties Marked Activity Creation Locked
67 0001 N/A 00:00:16 Dynamic No
28 0001 N/A 00:00:19 Dynamic No
65 0001 N/A 00:01:14 Dynamic No
42 0001 N/A 00:01:18 Dynamic No
32 0001 N/A 00:04:18 Dynamic No
* Total number of MeetMe users: 5
Please keep in mind that sometime there will be more than just 0001 Parties in the Conf Num. In the example above, I just want to grab the line:
32 0001 N/A 00:04:18 Dynamic No
This is the last line that has 0001 therefore assign $confnum="32"; to it.
Any kind of help I can get on this is greatly appreciated.
You can use exec instead of shell_exec and iterate through the output lines:
<?php
$output = array();
exec("asterisk -rx 'meetme list'", $output);
foreach ($output as $line) {
if (preg_match('/^32\s/', $line)) { //Check line starts with 32
echo $line;
}
}
Edit:
<?php
$output = array();
exec("asterisk -rx 'meetme list'", $output);
$lines = sizeof($output);
for ($i = $lines -1; $i >=0 ; $i--) {
if (preg_match('/^(\d+)\s+0001\s/', $output[$i], $matches)) { //Check line contains 0001
$firstNumber = $matches[1];
echo $firstNumber;
break;
}
}
Okay, assuming Linux, you can do this purely in shell:
filter last line: grep -v 'Total number of MeetMe isers'
filter first line: grep -v 'Conf Num'
and print only one Conf Num: awk 'BEGIN{ result=""; } {if( $2 == "0001"){result=$1;}} END {print result;}'
So the whole code:
$output = shell_exec("asterisk -rx 'meetme list' | grep -v 'Total number of MeetMe isers' | grep -v 'Conf Num' | awk 'BEGIN{ result=\"\"; } {if( \$2 == \"0001\"){result=$1;}} END {print result;}'");
// $output should contain your data :)
Or use preg_match_all():
$output = shell_exec("asterisk -rx 'meetme list'");
$matches = array();
$result = null;
preg_match_all('~^\s*(\\d+)\\s+0001~', $output, $matches, PREG_SET_ORDER);
foreach( $matches as $match ){
$result = $match[1];
}
In reaction to comment:
You should study regular expression syntax and meaning of \d and +. \d+ will match 0, 01 or 00000000000000000000000000000000 :).