adding string after every 'n' number of lines in a file using php - php

I have a .lst(playlist) file with around 1800 lines of data. Each line contains a URL to an audio file that is being played on my radio station.
The thing is I need to add URLs to some Advertisements after every 'n' number of lines in that file.
There are 10 URLs of advertisements from which 1 URL needs to be added after every 5 lines.
Example: URLs of Advertisements are in this format: file1.mp3, file2.mp3 ... file10.mp3
They will be added like this: file1.mp3 on line 5, file2.mp3 on line 10, file3.mp3 on line 15 and so on. After file10.mp3 has been inserted, it will again start from file1.mp3. I hope you understand.
So far I have managed to cook up the following code, but it only takes up one string to be added and have to manually tell the line number on which the string will be added. Unable to figure out the looping logic to do the aforementioned work.
$url = "/home/station/content/file1.mp3";
$line_number = 5; //add above URL on line number 5
$contents = file('playlist.lst', FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
if($line_number > sizeof($contents)) {
$line_number = sizeof($contents) + 1;
}
array_splice($contents, $line_number-1, 0, array($url));
$contents = implode("\n", $contents);
file_put_contents('playlist.lst', $contents);
How can I achieve this ?

You can use array_chunk to split your array into $line_number. Then, use array_map() to add your advertisements to each group. Finally, you could reduce to a linear array. You can format the $url using sprintf().
$url = "/home/station/content/file%d.mp3"; // use %d to use using sprintf()
$line_number = 5; //add above URL on line number 5
$counter = 1;
$contents = file('playlist.lst', FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
// split in group of $line_number
$groups = array_chunk($contents, $line_number);
// for each group:
$groups = array_map(function($arr) use ($url, &$counter) { // pass $counter as reference
// format the link
$adv = sprintf($url, $counter++) ;
// restart to 1 if greater than 10
if ($counter > 10) $counter = 1;
// append to group
$arr[] = $adv;
return $arr ;
},$groups);
// transform to linear array
$contents = array_reduce($groups, 'array_merge', array());
// save new file
file_put_contents('playlist.lst', implode("\n", $contents));

You could do it this way, with a simple loop:
//changing it to a "model" string, we are going to add the correct file number later
$url = "/home/station/content/file";
$contents = file('playlist.lst', FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
$count = 0;
$AddCount = 1;
//Loop until there is nothing left in our radio list
while ($count < sizeof($contents)) {
//if we have a multiple of 5, we are inserting an ad
if (($count % 5) == 0) {
// to know wich ad to add we use our AddCounter
$tmp = $url . strval($AddCount) . ".mp3";
//As suggested by Justinas, don't forget that each time you had a line you need to also increase the index for the next one using $count%5 to know how many lines you already added
array_splice($contents, $count - 1 + ($count % 5) , 0, array($tmp));
$AddCount += 1;
if ($AddCount > 10)
$AddCount = 1;
}
$count += 1;
}
$contents = implode("\n", $contents);
file_put_contents('playlist.lst', $contents);
This way, you don't even have to handle the advertisements file selection yourself as long as they are all formated like you said.

You should do a loop in such way.
$line_number = 5;
$line_count = 0;
for($i=0; $i < sizeof($contents); $i++)
{
$line_count = $line_count +1; // start with Line 1 that +1
if($line_count == $line_number)
{
// do your magic code of adding a line
$line_count = 0; // refresh counting from the beginning
}
}

You don't need to handle each line in the file one at a time.
Leave the file contents as its original string, inject placeholders with regex, then replace those placeholders with your ad array strings.
Code: (Basic Demo)
$filename = 'playlist.lst';
file_put_contents(
$filename,
vsprintf(
preg_replace(
'/(?:.+(\R)){5}\K/', // match (and forget) 5 lines, capture the newline character
'%s\1', // inject the placeholder following the the newline character
file_get_contents($filename),
count($ads) // make the exact number of needed placeholders
),
$ads // replace the placeholders with the ad strings
)
);

Related

Issue with searching for a word from 2 differents text files

I've been pulling my hair for the couple last hours, I can't figure this out, all I'm trying to do is to take 1 line from list.txt file then search for a match in source.txt file, here is my code
<?php
//Let's open the file
$list = #fopen("files/list.txt", "r");
$source = #fopen("files/source.txt", "r");
//I'm calculating number of lines in list.txt
$no_of_lines = count(file('files/list.txt'));
//I created 2 loops
//The first loop is to repeat the process based on the total number of lines in list.txt
//the second loop is the extract only 1 entry from the list.txt and search for a match in source.txt
for ($x=1; $x <= $no_of_lines ; $x++) {
for ($i=1; $i <= 1 ; $i++) {
$getLine = fgets($list);
$matches = array();
if ($source)
{
while (!feof($source))
{
$buffer = fgets($source);
if(strpos($source, $getLine) !== FALSE)
$matches[] = $buffer;
}
fclose($source);
}
}
}
//show results:
print_r($matches);
+source.txt has numbers from 1 to 100, each number in a separate line.
+list.txt has these numbers:
5
20000
1000000
87456
Current Error: Warning: strpos() expects parameter 1 to be string, resource given in C:\laragon\www\SearchFind\test2.php on line 26
I've tried many stackexchange solutions but nothing worked out.
There's no need to count the lines in list.txt first. Just loop calling fgets() until you get to the end of the file.
You need to initialize the $matches array before the loop. Otherwise you clear it out before searching for each number, and the final value will just be the matches for the last number in list.txt.
You need to reopen source.txt each time through the outer loop so you can read from it again.
You should be searching $buffer in the strpos() call, not $source (that's the reason for the error you're getting).
Don't use while (!feof($source)). Use while ($buffer = fgets($source)). fgets() returns FALSE when you get to the end of the file.
You need to use rtrim($getLine) and `rtrim($buffer) to remove the newline at the end of the line, so you're just searching for the number.
for ($i=1; $i <= 1 ; $i++) serves no purpose at all. It just loops one time, which is the same as not looping at all.
If you want to match the whole line, not just look for a substring, use === to compare $getLine and $buffer, not strpos().
<?php
//Let's open the file
$list = fopen("list.txt", "r");
$matches = array();
if ($list) {
while ($getLine = fgets($list)) {
$getLine = rtrim($getLine); // remove newline
$source = fopen("source.txt", "r");
if ($source)
{
while ($buffer = fgets($source)) {
$buffer = rtrim($buffer);
if($buffer === $getLine)
$matches[] = $buffer;
}
fclose($source);
}
}
}
//show results:
print_r($matches);

How do I print the triangular series onto a file using PHP?

What i'm trying to do is create a file with the name triangular_10.txt where the number in the file name is the number the user entered. From there I want the text file to have the triangular series of numbers. So if the user enters 10, it'll display the first 10 numbers of the triangular series. So far the file name change is working.
The algorithm is here that I used for PHP:
http://www.codecodex.com/wiki/Calculate_a_triangle_number
eg. user enters 10. Result in txt file is first 10 numbers in the triangular series = [1, 3, 6, 10, 15, 21, 28, 36, 45]
This is what I have so far but I'm not having any luck! At the moment its only writing the number I entered on to the txt file and nothing else!
$number = $_POST['number-entered'];
foreach(range(1, 1000) as $i) {
$triangle_numbers[] = $i * ($i + 1) / 2;
}
//make a file
$contents = fopen('gs://a1-task22020.appspot.com/triangular_'.$number. ".txt", "w");
fwrite($contents, $number);
//open the file
$contents = fopen('gs://a1-task22020.appspot.com/'.$contents, 'w');
// re-open the document if you put something in it
fwrite($contents, $number);
fclose($contents);
}
}
Since I got confirmed that saving to file itself is not an issue, I am posting 3 solutions
$number = intval($_POST['number-entered']); // convert target number to string;
$triangle_numbers = [];
// SOLUTION 0 (no change to your loop, but you should use something else, range(1,1000) is very bad there)
foreach (range(1, 1000) as $i) {
$triangle_numbers[] = $i * ($i + 1) / 2;
}
$triangle_numbers = array_slice($triangle_numbers,0,$number);
// SOLUTION 1:
foreach ( range(1, $number) as $i ) { //we don't need to go all the way to 1000 if user only wants 5, and if they want 2000 we are covered
$triangle_numbers[] = $i * ( $i + 1 ) / 2;
}
// SOLUTION 2
for ($i = 1; $i<=$number; $i++) { //it's as above, i just changed the loop
$triangle_numbers[] = $i * ($i + 1) / 2;
}
// rest is pretty much the same
//edit, i removed weird reopen part. it made you write to the same line over and over
$contents = fopen('here.txt', "w");
fwrite($contents, $number . "\n");
fwrite($contents, implode(', ', $triangle_numbers)); // read https://www.php.net/manual/en/function.implode.php
fwrite($contents, "\n$number\n");
fclose($contents);

PHP read every 3rd line from file and save it to another file

I want to read every 3rd line from file1 and save it as a new file2.
This is what I am trying, but it doesn't work. Any ideas?
$myfile = file("file1.txt");
$lines = file($myFile);
$newFileContent= $lines[2];
file_put_contents("file2.txt", $newFileContent);
So, if file1.txt has the following content:
1
2
3
4
5
6
The file2.txt should contain only:
3
6
The actual easiest way would be to use a normal for loop. The array is non-associative, so it makes no sense to use an expensive foreach over the entire array.
To exactly replicate your sample data, just use something like the following:
$lines = file('file1.txt');
$newContent = '';
$len = count($lines); // saves us from calling count() on every iteration
for ($i = 2; $i < $len; $i += 3) {
$newContent .= $lines[$i];
}
file_put_contents('file2.txt', $newContent);
Working demo

How to sum column text file

Hello everyone and I immediately apologize, as
I have seen various threads on the site, but unfortunately my knowledge is still insufficient to complete my project.
I have a text file and I have to do the sum of each column (just need the total):
1003|name1|1208.00|2.00 |96.00 |0.00|0.00|0.00|0.00|98.00 |90.95 |7.05 |8516.40
1011|name2|1450.00|2.00 |49.00 |0.00|0.00|0.00|0.00|51.00 |44.62 |6.38 |9243.7
1004|name3|1450.00|25.00|170.00|0.00|0.00|0.00|0.00|195.00|175.75|19.25|27912.5 <br>
1002|name4|765.00 |1.00 |17.00 |0.00|0.00|0.00|0.00|18.00 |15.13 |2.87 |2193.26
I need to get this(I have this file on linux then we can use Bash, PHP, Mysql... ):
1003|name1|1208.00|2.00 |96.00 |0.00|0.00|0.00|0.00|98.00 |90.95 |7.05 |8516.40
1011|name2|1450.00|2.00 |49.00 |0.00|0.00|0.00|0.00|51.00 |44.62 |6.38 |9243.7
1004|name3|1450.00|25.00|170.00|0.00|0.00|0.00|0.00|195.00|175.75|19.25|27912.5 <br>
1002|name4|765.00 |1.00 |17.00 |0.00|0.00|0.00|0.00|18.00 |15.13 |2.87 |2193.26 <br>
xxxx|Total |4873.00|30.00|332.00|0.00|0.00|0.00|0.00|362.00 |326.45|35.55|47865.86
Where xxxx is the Id number (No sum here).
I've been trying to do this in PHP and MySQL -- No luck so far.
try something like:
$file = '/path/to/your_file.txt';
if ( ($file = fopen($file, "r")) !== FALSE) {
$total = 0;
$row_1 = 0;
while (($line = fgetcsv($file, 1000, "|")) !== FALSE) {
// brutal dirt sanitization
foreach ( $line as $k => $v ) {
$line[$k] = (float) preg_replace('#[^0-9\.]#','', $v);
}
$total = $total + array_sum(array_slice($line, 2));
$row_1 = $row_1 + array_sum(array_slice($line, 2, 1));
//...
}
echo $total.' | '.$row_1; //...
}
else echo 'error ...';
also, you can sanitize each row by replacing array_sum() by array_map() wih a callback function
Psuedocode:
open source file for reading
open destination file for writing
initialise totaling array to zero values
while not EOF
read in line from file
explode line into working array
for x=2 ; x<14; x++
add totalling array with floatval( working array )
write line out to destination file
close read file
write out totals array to destination file
close destingation file
Try to get the text file data into an excel spreadsheet and then add up the columns.
You can use VB to get the text into excel and then continue adding up the values of each column.
1) replace all | chars with , using str_replace
2) Use str_getcsv to create array out of the above resulting csv string
3) use foreach and loop through each row and calculate total
some PHP code
$str = file_get_contents('myfile.txt');
$str = str_replace('|', ',', $str);
$csv = str_getcsv($str);
$totals = array(0,0,0,0);
foreach ($csv as $row) {
$totals[0] += trim($row[0]);
$totals[1] += trim($row[2]);
$totals[2] += trim($row[3]);
$totals[3] += trim($row[4]);
}
the $totals array contains all totals!

PHP Grab last 15 lines in txt file

Thank you for taking the time to read this and I will appreciate every single response no mater the quality of content. :)
Using PHP, I'm trying to get the last 15 lines of a text document (.txt) and store that data into a php variable. I understand that this is possible, however when I do get the last 15 lines, is it possible to retain the order? For example:
text document:
A
B
C
When I grab the text document from the last 15 characters, I don't want the echo to end up like:
C
B
A
All assistance is appreciated and I look forward to your replies; thank you. :) If I didn't explain anything clearly and/or you'd like me to explain in more detail, please reply. :)
Thank you.
Try using array_slice, which will return a part of an array. In this case you want it to return the last 15 lines of the array, so:
$filearray = file("filename");
$lastfifteenlines = array_slice($filearray,-15);
If you don't mind loading the entire file into memory:
$lines = array_slice(file('test.txt'), -15);
print_r($lines );
If the file is too large to fit into memory you can use a circular method:
// Read the last $num lines from stream $fp
function read_last_lines($fp, $num)
{
$idx = 0;
$lines = array();
while(($line = fgets($fp)))
{
$lines[$idx] = $line;
$idx = ($idx + 1) % $num;
}
$p1 = array_slice($lines, $idx);
$p2 = array_slice($lines, 0, $idx);
$ordered_lines = array_merge($p1, $p2);
return $ordered_lines;
}
// Open the file and read the last 15 lines
$fp = fopen('test.txt', 'r');
$lines = read_last_lines($fp, 15);
fclose($fp);
// Output array
print_r($lines);
This method will also work if the file has less than 15 lines- returning an array with however many lines are in the file.
You can use fseek with a negative position to seek backwards through the file, counting newlines as you go.
I'm too tired to write up copy/past-able code, but there are some examples in the comments to the manual page for fseek that are very close to what you want.
If the file isn't bigger than available memory you can do this:
$fArray = file("filename");
$len = sizeof($fArray);
for($i=$len -15;$i<$len ;$i++)
{
echo $fArray[$i];
}
If you have a file that is hundreds of megabytes :
$rc = fopen("file","r");
for ($i=0; $line = fgets($file) ;$i++)
{
if ($i%15 == 0)
{
$last15 = array();
}
$last15[] = $line;
}
echo join("\n",$last15);
the longer array solution:
array_slice(explode("\n",file_get_contents($file)),-15);
the shorter array solution:
array_slice(file($file),-15);
This code will open the file, show the total lines, show the header of file and show the last lines of file defined in $limit.
<?php
// open the file in read mode
$file = new SplFileObject('file.csv', 'r');
// get the total lines
$file->seek(PHP_INT_MAX);
$last_line = $file->key();
echo $last_line;
echo "<br>";
// Rewind to first line to get header
$file->rewind();
// Output first line if you need use the header to make something
echo $file->current();
echo "<br>";
// selecting the limit
$limit = 6;
// selecting the last lines using the $limit
$lines = new LimitIterator($file, $last_line - $limit, $last_line);
//print all the last 6 lines array
//print_r(iterator_to_array($lines));
//echo "<br>";
// Loop over whole file to use a single line
foreach ($lines as $line) {
print_r($line);
echo "<br>";
}

Categories