Write data on specific line into the file with PHP - php

Is there way to append data to file on specific line or something similar like that?
I have an "handmade" array in my file, and I need to keep my beginning and end of the array.
I would like to have something like this:
$array = [
*create new line and write data here*,
*previous data*,
*previous data*,
*previous data*,
];
EDIT: I currently only know how to append data at the end of the file, and I haven't found proper solution. If I append my data with just file_put_contents();, it won't be in the array:
$array = [
*previous data*,
*previous data*,
*previous data*,
];
*create new line and write data here*,
EDIT: I got my answer. There is no efficient way to do this.

You can't add a line in a middle of a file.
You need to rewrite the file with something like this (not memory expensive) :
// Read your old file
$read = fopen('myfile', 'r');
// Create a new file
$write = fopen('myfile.tmp', 'w');
while (!feof($read)) {
$line = fgets($read);
if (stristr($line, '$arr = [')) { // For your case
$line .= "YOUR NEW LINE\n";
}
fputs($write, $line);
}
fclose($read);
fclose($write);
// Rename the new file
rename('myfile.tmp', 'myfile');

If writing to a file, there are not many (any, in my personal experience!) options for efficient prepending or mid-file inserts. Almost all of the working world relies on appending to files. You can do it, but only through basically rewriting the entire file. In essence, you have to "move all the other lines down", and that takes work.
If this is something you need done efficiently, consider a more appropriate data structure. Perhaps multiple arrays (e.g., perhaps in reverse order), multiple files, a sorting key for after load sorting, etc. But you are not likely to get around the issue of slow performance when prepending or inserting to on-disk files. (And if you do, likely involving some kernel editing, then consider making some money or helping the FOSS world out!)
If you are doing this in memory, then the data structures and access patterns are much more robust, and so you can do operations like array_unshift:
$arr = [
"line 1",
"line 2",
"line ..."
];
array_unshift($arr, "line 0");
# $arr is now: [
# "line 0",
# "line 1",
# "line 2",
# "line ..."
#];

To add elements at the beginning of an array use array_unshift:
$a=array ("content of a line", "another line");
array_unshift($a, "content to be added");
print_r($a); //print out to check
'array_push' does the same but add element(s) at the end of the array

Related

How to delete first 11 lines in a file using PHP?

I have a CSV file in which I want the first 11 lines to be removed. The file looks something like:
"MacroTrends Data Download"
"GOOGL - Historical Price and Volume Data"
"Historical prices are adjusted for both splits and dividends"
"Disclaimer and Terms of Use: Historical stock data is provided 'as is' and solely for informational purposes, not for trading purposes or advice."
"MacroTrends LLC expressly disclaims the accuracy, adequacy, or completeness of any data and shall not be liable for any errors, omissions or other defects in, "
"delays or interruptions in such data, or for any actions taken in reliance thereon. Neither MacroTrends LLC nor any of our information providers will be liable"
"for any damages relating to your use of the data provided."
date,open,high,low,close,volume
2004-08-19,50.1598,52.1911,48.1286,50.3228,44659000
2004-08-20,50.6614,54.7089,50.4056,54.3227,22834300
2004-08-23,55.5515,56.9157,54.6938,54.8694,18256100
2004-08-24,55.7922,55.9728,51.9454,52.5974,15247300
2004-08-25,52.5422,54.1672,52.1008,53.1641,9188600
I want only the stocks data and not anything else. So I wish to remove the first 11 lines. Also, there will be several text files for different tickers. So str_replace doesn't seem to be a viable option. The function I've been using to get CSV file and putting the required contents to a text file is
function getCSVFile($url, $outputFile)
{
$content = file_get_contents($url);
$content = str_replace("date,open,high,low,close,volume", "", $content);
$content = trim($content);
file_put_contents($outputFile, $content);
}
I want a general solution which can remove the first 11 lines from the CSV file and put the remaining contents to a text file. How do I do this?
Every example here won't work for large/huge files. People don't care about the memory nowadays. You, as a great programmer, want your code to be efficient with low memory footprint.
Instead parse file line by line:
function saveStrippedCsvFile($inputFile, $outputFile, $lineCountToRemove)
{
$inputHandle = fopen($inputFile, 'r');
$outputHandle = fopen($outputFile, 'w');
// make sure you handle errors as well
// files may be unreadable, unwritable etc…
$counter = 0;
while (!feof($inputHandle)) {
if ($counter < $lineCountToRemove) {
fgets($inputHandle);
++$counter;
continue;
}
fwrite($outputHandle, fgets($inputHandle) . PHP_EOL);
}
fclose($inputHandle);
fclose($outputHandle);
}
I have a CSV file in which I want the first 11 lines to be removed.
I always prefer to use explode to do that.
$string = file_get_contents($file);
$lines = explode('\n', $string);
for($i = 0; $i < 11; $i++) { //First key = 0 - 0,1,2,3,4,5,6,7,8,9,10 = 11 lines
unset($lines[$i]);
}
This will remove it and with implode you can create a new 'file' out of it
$new = implode('\n',$lines);
$new will contain the new file
Did'nt test it, but I'm pretty sure that this will work
Be carefull! I will quote #emix his comment.
This will fail spectacularly if the file content exceeds available PHP memory.
Be sure that the file isn't to 'huge'
Use file() to read it as array and simply trim first 11 lines:
$content = file($url);
$newContent = array_slice($content, 12);
file_put_contents($outputFile, implode(PHP_EOL, $newContent));
But answer these questions:
Why there is additional content in this CSV?
How will you know how much lines to cut off? What if it's more than 11 lines to cut?

How to turn raw textfile data into json using PHP?

I was given a task to sort out data from a text file into JSON using PHP and object oriented principal.
The text file has information and is displayed as follows (ignore #):
#product_num:name:cost
5:tv:59.99
7:radio:10.99
I created a class and in this class I have one function that ignores any # or blank spaces from the data and puts the data in an array and json_encode it. When I echo this data it looks like this:
[{"1":"5:tv:59.99","2":"7:radio:10.99"}]
Is it possible to write other functions to separate the data further, for example so it looks more like:
[{"product_number":"5","name":"tv","cost":"59.99"},{"product_number":"7","name":"radio","cost":"10.99"}]
If so can anyone give me any pointers and tips because I have no idea where or how to begin even after numerous google searches.
There is a function inside PHP for reading value separated lines, like CSV; it's called fgetcsv which can also be used in object oriented PHP through SplFileObject::fgetcsv.
You will need to read each line, add the variable labels then append that to an array.
Depending on the size of the file you may need to optimize for memory usage as your array grows by saving as you proceed through the file.
<?php
$file = new SplFileObject('test.txt', 'r'); //Load the file
$file->current(); //Skip the first line (Side note: seek(1) did not appear to work while testing)
$result = [];
do { //While there are lines in the file
list($product_num, $name, $cost) = $file->fgetcsv(':'); //Break the line on the : delimiter into an array and populate the array into the three named values
$result[] = [ //Build the new json representation and add to result array
'product_num' => $product_num,
'name' => $name,
'cost' => $cost,
];
} while (!$file->eof());
file_put_contents('output.json', json_encode($result)); //Save the result
Your file format is basically a csv file and PHP has a CSV import function.
http://php.net/manual/en/function.fgetcsv.php
If you scroll down and check the CsvImporter example, you can copy/paste that and add a json_encode:
$importer = new CsvImporter("small.txt",true,":");
$data = $importer->get();
echo json_encode($data);
[{
"\ufeff#product_num": "5",
"name": "tv",
"cost": "59.99"
},
{
"\ufeff#product_num": "7",
"name": "radio",
"cost": "10.99"
}]

How to exclude the first line from a text file using php

My text file sample.txt. I want to exclude the first row from the text file and store the other rows into mysql database.
ID Name EMail
1 Siva xyz#gmail.com
2 vinoth xxx#gmail.com
3 ashwin yyy#gmail.com
Now I want to read this data from the text file except the first row(ID,name,email) and store into the MYsql db.Because already I have created a filed in database with the same name.
I have tried
$handle = #fopen($filename, "r"); //read line one by one
while (!feof($handle)) // Loop till end of file.
{
$buffer = fgets($handle, 4096); // Read a line.
}
print_r($buffer); // It shows all the text.
Please let me know how to do this?
Thanks.
Regards,
Siva R
It's easier if you use file() since it will get all rows in an array instead:
// Get all rows in an array (and tell file not to include the trailing new lines
$rows = file($filename, FILE_IGNORE_NEW_LINES);
// Remove the first element (first row) from the array
array_shift($rows);
// Now do what you want with the rest
foreach ($rows as $lineNumber => $row) {
// do something cool with the row data
}
If you want to get it all as a string again, without the first row, just implode it with a new line as glue:
// The rows still contain the line break, since we only trimmed the copy
$content = implode("\n", $rows);
Note: As #Don'tPanic pointed out in his comment, using file() is simple and easy but not advisable if the original file is large, since it will read the whole thing into memory as an array (and arrays take more memory than strings). He also correctly recommended the FILE_IGNORE_NEW_LINES-flag, just so you know :-)
You can just call fgets once before your while loop to get the header row out of the way.
$firstline = fgets($handle, 4096);
while (!feof($handle)) // Loop till end of file.
{ ...

How to update a .txt file using PHP

My colleague and I are working on a chat application for a small Flash based game. We would like to keep our chat file as small as possible by automatically deleting old text after the file has reached a certain limit. Say the file exceeds 50 lines, we would like to delete the existing information and begin again at line 1. Is this possible?
<?php
$file = "saved.txt";
$edited_text = $_POST['new_text'];
$open = fopen($file, "a+");
fwrite($open, "\n" . $edited_text);
fclose($open);
?>
Basically something like this:
$lines = file('saved.txt');
$lines[] = 'new line of text';
array_unshift($lines); // remove first array element
file_put_contents('saved.txt', implode(PHP_EOL, $lines));
Read the file into an array, one line per array element
Append your new line(s) of text
Remove as many lines from the start of the array as necessary
dump array back out to file as text.
This would work:
// Read entire file
$lines = file_get_contents('saved.txt');
// Add what you want to the beginning of array
array_unshift($lines, 'new line of text');
// Keep first 50 items
$lines = array_splice($lines, 0, 50);
// Write them back
file_put_contents('saved.txt', implode(PHP_EOL, $lines));
Will always keep the first 50 elements intact (which includes messages from new to old).

how to insert value in a particular location in csv file using php

Is it possible to write at a particular location in a CSV file using PHP?
I don't want to append data at the end of the CSV file. But I want to add data at the end of a row already having values in the CSV.
thanks in advance
No, it s not possible to insert new data in the middle of a file, due to filesystem nature.
Only append at the end is possible.
So, the only solution is to make another file, write a beginning part of source, append a new value, and then append the rest of the source file. And finally rename a resulting file to original name.
There you go. Complete working code:
<?php
//A helping function to insert data at any position in array.
function array_insert($array, $pos, $val)
{
$array2 = array_splice($array, $pos);
$array[] = $val;
$array = array_merge($array, $array2);
return $array;
}
//What and where you want to insert
$DataToInsert = '11,Shamit,Male';
$PositionToInsert = 3;
//Full path & Name of the CSV File
$FileName = 'data.csv';
//Read the file and get is as a array of lines.
$arrLines = file($FileName);
//Insert data into this array.
$Result = array_insert($arrLines, $PositionToInsert, $DataToInsert);
//Convert result array to string.
$ResultStr = implode("\n", $Result);
//Write to the file.
file_put_contents($FileName, $ResultStr);
?>
Technically Col. Shrapnel's answer is absolutely right.
Your problem is that you don't want to deal with all these file operations just to change some data. I agree with you. But you're looking for the solution in a wrong level. Put this problem in a higher level. Create a model that represents an entity in your CSV database. Modify the model's state and call its save() method. The method should be responsible to write your model's state in CSV format.
Still, you can use a CSV library that abstracts low level operations for you. For instance, parsecsv-for-php allows you to target a specific cell:
$csv = new parseCSV();
$csv->sort_by = 'id';
$csv->parse('data.csv');
# "4" is the value of the "id" column of the CSV row
$csv->data[4]['firstname'] = 'John';
$csv->save();

Categories