This is some of the weirdest stuff I've ever honestly seen.
$filename = "/etc/httpd/conf/httpd.conf";
$handle = fopen($filename, "r+");
$size = filesize($filename);
$contents = fread($handle, $size);
fwrite($handle,$contents);
fclose($handle);
Shouldn't this read the contents of the file then write it again? Basically leaving the file unmodified? At this moment this piece of code does exactly what append does, it duplicates the contents of the file adding $contents at the end of the file, and I have no idea why. I tried changing the string a little before writing it and that's how I found out it writes to the end, not the beginning.
Your fread() is advancing the file pointer such that by the time you call fwrite, your file pointer is at the end and your write appends to the file from there.
If you want to write to the file starting at the beginning after reading it all in then:
rewind($handle);
Related
I have a very large file that consists of a single string. Because of the size of the file, I do not want to read the entire string into memory.
The last character will always be a closing bracket ] as this string is a json array. I want to insert a small json object (represented as a string) immediately before that closing bracket. I have seen a few ideas, but cannot get anything to work.
As you can see, I am trying to open the file and use fseek to move the file pointer to just in front of the ]. Then I try to write the new string into the existing string at that position.
However, the effect of this is simply to append the new string to the end of the existing string, which is not what I want.
As a simplified example, let's say the file starts out containing this string:
[{"name":"alice","city":"london"}]
And then I want to add a second person to this list using this code:
$new_person = ",{\"name\":\"bob\",\"city\":\"paris\"}";
$filename = "people.json";
$fh = fopen($filename, "a+");
$filesize = filesize($filename);
$stat = fstat($fh);
fseek($fh, $stat[$filesize]-1);
fwrite($fh, $new_person);
fclose($fh);
But what I wind up with is a file that contains this string:
[{"name":"alice","city":"london"}],{"name":"bob","city":"paris"}
My PHP skills are terrible. I can't tell if my fseek is pointing to the wrong spot or if the issue is elsewhere. Thanks for any help.
From the docs (emphasis mine):
a+: Open for reading and writing; place the file pointer at the end of the file. If the file does not exist, attempt to create it. In this mode, fseek() only affects the reading position, writes are always appended.
Use r+ mode instead, and instead of fstat you can do:
fseek($fh, -1, SEEK_END);
Please try the following code to get your solution, i have tested and its work fine...
try{
$new_person = ",{\"name\":\"bob\",\"city\":\"paris\"}]";
$filename = "people.json";
$fh = fopen($filename, "a+");
$stat = fstat($fh);
ftruncate($fh, $stat['size'] - 2);
fwrite($fh, $new_person);
fclose($fh);
}catch(Exception $exc){
echo($exc->getMessage());
}
I'm going through all the modes and trying to understand where can you apply some of them, and I stumbled upon w. Now I understand how that mode works, but what's the purpose of w+? Obviously if we use fopen right after opening the file, it won't work since the file will be truncated, so I assume it's good to write something in the file and then read from it later on, so I decided to test it like so:
$handle = fopen('new.txt', 'w+');
fwrite($handle, '123');
$file = fread($handle, filesize('new.txt'));
var_dump($file); // string '' (length=0)
fclose($handle);
For some reason it doesn't read the contains of the file later.
Could someone explain to me please where could it applicable, and what is wrong with my code? filesize returns 3, so it doesn't delete the contents of the file, I assume that the $handle might be used from the moment we opened the file and it doesn't update? Then it confuses me even more why would we use mode w+ and doing reading from a file at the same time?
Edit: I can understand even how I can write something in the file with r+ and then check what I've written with using fopen again, like so:
$handle = fopen('new.txt', 'r+');
fwrite($handle, '123');
$handle = fopen('new.txt', 'r+');
$file = fread($handle, filesize('new.txt'));
var_dump($file);
fclose($handle);
If I would do the same with w+, it would just delete the contents obviously, and I would not be able to read anything?
fopen() with w+ option opens the file for read/write at the beginning and truncates the length to 0. It's essentially the same as writing to a new empty file.
See fopen() usage here: http://php.net/manual/en/function.fopen.php
w+ is mainly used to "read back" what you've written. In your case you are using fread() function which reads "forward" from your pointer which is currently sitting at the end of the file after doing fwrite(), which would explain why you are getting empty contents.
I hope this answers your question.
#Ye. is right about the pointer. Once you have executed fwrite, then the pointer will be at the end of the file. What you need is fseek() to go back to the beginning of the file.
$handle = fopen('new.txt', 'w+');
fwrite($handle, '123');
fseek($handle, 0);
$file = fread($handle, filesize('new.txt'));
var_dump($file); // string '123' (length=3)
fclose($handle);
I have a code in which should open an existing text file into my server, save the text into a variable, then filter the text contained within this variable and save again, as you can see below:
Text File:
Descrição: lorem impsum is a dollar do dolla do dolla style user humam
Source Code:
$filename = "prods/".$value;
$handle = fopen($filename, "w+");
$contents = fread($handle, filesize($filename));
$newcontent .= str_replace("Descrição:", "Descricao:", $contents);
fwrite($handle,$newcontent);
fclose($handle);
The problem is the command write is saving the file again with null text inside him, how can I solve this?
According to http://php.net/manual/en/function.fopen.php:
'w+' Open for reading and writing; place the file pointer at the beginning of the file and truncate the file to zero length. If the file does not exist, attempt to create it.
You are therefore reading an empty string, and writing such a string back too.
The simplest way to solve your problem might be:
$filename = "prods/".$value;
$contents = file_get_contents($filename);
$newcontent .= str_replace("Descrição:", "Descricao:", $contents);
file_put_contents($filename, $newcontent);
Your problem is the mode 'w+' you use for fopen.
I think a+ is the one you're looking for.
w+ mode truncates the file to 0 length. You want to use c+ or file_get_contents(), then file_put_contents() instead.
I test this PHP code on windows and it first removes the file.txt contents and then write the new contents on it.
$f = fopen('file.txt', 'r+');
fwrite($f, "first-time");
fclose($f);
Every time I execute this code and see file.txt, it has ONE "first-time" in it.
I expect it to prepend "first-time" to the old file. like:
first-timefirst-timefirst-time and so on.
Why r+ acts like w+ in making zero length?
Answer to your question: Your code does not truncate the file, but simply overwrites the previous content.
Quick and dirty solution for the behaviour your want to achieve:
<?php
$file_data = "Stuff you want to add\n";
$file_data .= file_get_contents('file.txt');
file_put_contents('file.txt', $file_data);
?>
EDIT:
The answer can be found here:
How do I prepend file to beginning?
According to the PHP fopen manual:
'r+' Open for reading and writing; place the file pointer at the beginning of the file.
'a+' Open for reading and writing; place the file pointer at the end of the file. If the file does not exist, attempt to create it.
$f = fopen('file.txt', 'a+');
fwrite($f, "fisrt-time");
fclose($f);
So if you'd like to append content, use a+ mode.
I tried to use fopen, but I only managed to append content to end of file. Is it possible to overwrite all contents with new content in PHP?
Use file_put_contents()
file_put_contents('file.txt', 'bar');
echo file_get_contents('file.txt'); // bar
file_put_contents('file.txt', 'foo');
echo file_get_contents('file.txt'); // foo
Alternatively, if you're stuck with fopen() you can use the w or w+ modes:
'w' Open for writing only; place the file pointer at the beginning of the file and truncate the file to zero length. If the file does not exist, attempt to create it.
'w+' Open for reading and writing; place the file pointer at the beginning of the file and truncate the file to zero length. If the file does not exist, attempt to create it.
$fname = "database.php";
$fhandle = fopen($fname,"r");
$content = fread($fhandle,filesize($fname));
$content = str_replace("192.168.1.198", "localhost", $content);
$fhandle = fopen($fname,"w");
fwrite($fhandle,$content);
fclose($fhandle);
MY PREFERRED METHOD is using fopen,fwrite and fclose [it will cost less CPU]
$f=fopen('myfile.txt','w');
fwrite($f,'new content');
fclose($f);
Warning for those using file_put_contents
It'll affect a lot in performance, for example [on the same class/situation] file_get_contents too: if you have a BIG FILE, it'll read the whole content in one shot and that operation could take a long waiting time