PHP: Problems reading and write back to file - php

$fh = fopen(PATH_TO_FILE, "r+");
flock($fh, LOCK_EX);
$data = fgets($fh);
$data = json_decode($data, true);
$data['mod_1'] = 1;
$data_write = json_encode($data);
ftruncate($fh, 0);
fwrite($fh , $data_write);
clearstatcache();
flock($fh, LOCK_UN);
fclose($fh);
This works only if I prepare JSON file by myself. The problem is, next time I try to call this method, json_decode() returns false and the file is partial corrupted. json_decode() can not parse it anymore.
What is the problem with this code?
My JSON File contents:
{"mod_1":0,"mod_2": 0}
All I want is to read file, modify its content and write back to file(overwrite). I must use LOCK_EX, so I assume file_put_contents is not for me.

The problem was that ftruncate didn't set the pointer at the beginning of empty file. So I added rewind($fh) right after ftruncate and the problem was solved.

Related

PHP Lock file while reading - flock() makes my file blank

As you can see in the code below, I'm trying to use flock to prevent other clients to acess the php (actually multiple users will acess this something like 10 times per second, each one), as I've found searching here... But this is not working. My data.txt is getting blank everytime doing this.
<?php
$fileName = $_GET["room"]."/data.txt";
function replaceLine($data){
if (stristr($data, $_GET["player"])){
return $_GET["player"]." ".$_GET["data"]."\n";
}
return $data;
}
$file = fopen($fileName,"r");
if (flock($file, LOCK_EX)){
//ftruncate($file, 0);
///--------------
$data = file($fileName);
$data = array_map("replaceLine", $data);
file_put_contents($fileName, implode('', $data));
echo fread($file, filesize($fileName)+1);
///--------------
fflush($file);
flock($file, LOCK_UN);
} else {
echo "wait";
}
fclose($file);
?>
This is the original code (that I was trying to modify to prevent making the file empty): (It works as I want, but have this file problem...)
<?php
$fileName = $_GET["room"]."/data.txt";
function replaceLine($data){
if (stristr($data, $_GET["player"])){
return $_GET["player"]." ".$_GET["data"]."\n";
}
return $data;
}
$data = file($fileName);
$data = array_map("replaceLine", $data);
file_put_contents($fileName, implode('', $data));
$file = fopen($fileName,"r");
echo fread($file, filesize($fileName)+1);
fclose($file);
?>
Sorry for asking this newbie question, but I have not idea how to fix this and I'm searching and trying different things for weeks! Thanks!
You are opening the file for read only and then you are attempting to write to that same file. Try setting the fopen parameter to read/write.
$file = fopen($fileName,"r+");
I would also use fwrite() instead of file_put_contents() since you already have the file pointer and opening it again will likely be denied by the lock.

Create CSV File in PHP and Save to SFTP using phpseclib

I need to generate a CSV file from a MySQL query and save the file to an SFTP server. I have tried the code below. The CSV file gets created, but it is empty. I also receive an error message in the browser that says Warning: is_file() expects parameter 1 to be a valid path, resource given in regard to this line $sftp->put($fileName, $fp, NET_SFTP_LOCAL_FILE);. If I move fclose($fp); to the last line, I don't get the error but data still doesn't appear in the file. Could someone please let me know how to get the data to save in the file that was created?
$fileName = 'dataFiles/reports/Report Summary/Report Summary.csv';
$sql = mysqli_query($db, "
SELECT *
FROM reports
WHERE reportID = 1
");
$fp = fopen('php://output', 'w');
$first = true;
while($row = mysqli_fetch_assoc($sql)){
if ($first) {
fputcsv($fp, array_keys($row));
$first = false;
}
fputcsv($fp, $row);
}
fclose($fp);
$sftp->put($fileName, $fp, NET_SFTP_LOCAL_FILE);
Try something like this:
<?php
$fp = fopen('php://temp', 'r+');
// do stuff
rewind($fp);
$sftp->put($filename, $fp);
phpseclib (assuming you're using a new enough version) will detect that the second parameter is a stream resource and will try to read from it accordingly.
The second argument is not a handle but the content directly.
I think you could do: stream_get_contents($fp); in the second argument.
$content = stream_get_contents($fp);
fclose($fp);
$sftp->put($fileName, $content, NET_SFTP_LOCAL_FILE);

Load file lines into an array AFTER the file is open and locked (PHP)

Is there a quick way to load every line of a file into an array from a file once it has already been opened?
For example:
$handle = fopen("file", "r+");
flock($handle, LOCK_EX);
$array = load_lines($handle); <- need this
// compute on the array
fwrite($handle, $array);
flock($handle, LOCK_UN):
fclose($handle);
The reason I need this is because I currently use the file() function to grab the contents of a file and put them into an array. However, I need to incorporate file locking into my design and I'm hoping to not have to change it too much (it is current array-based). Is there an easy way to do this?
On php <5.3, or if you choose to with LOCK_NB, file locks in php are advisory. That is, you have to test the lock yourself .. they don't actually prevent you from updating the file. This will do:
$fh = fopen(__FILE__, 'r+');
if (flock($fh, LOCK_EX)) {
$array = file(__FILE__);
fwrite($fh, implode($array));
flock($fh, LOCK_UN);
flcose($fh);
}
else {
echo "Could not acquire the lock!"
}
I also tested this out in php 5.3. It seems that file() ignores locking.
Try this:
function load_lines($handle)
{
$array = array();
while(!feof($handle)
{
$array[] = fgets($handle);
}
return $array;
}

fread a file that is changing

Provided the following example code:
<?php
$handle = fopen("/tmp/test_file/sometestfile", "r");
$contents = '';
while (!feof($handle)) {
$contents = fread($handle, 10);
print $contents;
sleep(1);
}
fclose($handle);
?>
If sometestfile, which is a txt file in my case, changes during the read loop, why is the php program continuing to read from the old file?
Say it is full of 1's and I cat sometestfile_new over it which is full of 2's.
I am running this on Linux, is this inode related?
If rewind() is added after each loop, the new file will be read instead, after the overwrite point in time.
from php.net
resource fopen ( string $filename , string $mode [, bool $use_include_path = false [, resource $context ]] )
fopen() binds a named resource, specified by filename, to a stream.
the fopen() as soon as it's called it "caches" the file and will output in the method you mention, example is your $contents = fread($handle, 10);
You can delete the file and it will still read that resource until it finishes the file !feof($handle)
You cannot do anything else with fopen(), you just can't reread the source and continue to print it.

How to write into a file in PHP?

I have this script on one free PHP-supporting server:
<html>
<body>
<?php
$file = fopen("lidn.txt","a");
fclose($file);
?>
</body>
</html>
It creates the file lidn.txt, but it's empty.
How can I create a file and write something into it,
for example the line "Cats chase mice"?
You can use a higher-level function like:
file_put_contents($filename, $content);
which is identical to calling fopen(), fwrite(), and fclose() successively to write data to a file.
Docs: file_put_contents
Consider fwrite():
<?php
$fp = fopen('lidn.txt', 'w');
fwrite($fp, 'Cats chase mice');
fclose($fp);
?>
$fp = fopen('lidn.txt', 'w');
fwrite($fp, 'Cats chase');
fwrite($fp, 'mice');
fclose($fp);
http://php.net/manual/en/function.fwrite.php
$text = "Cats chase mice";
$filename = "somefile.txt";
$fh = fopen($filename, "a");
fwrite($fh, $text);
fclose($fh);
You use fwrite()
It is easy to write file :
$fp = fopen('lidn.txt', 'w');
fwrite($fp, 'Cats chase mice');
fclose($fp);
Here are the steps:
Open the file
Write to the file
Close the file
$select = "data what we trying to store in a file";
$file = fopen("/var/www/htdocs/folder/test.txt", "w");
fwrite($file, $select->__toString());
fclose($file);
I use the following code to write files on my web directory.
write_file.html
<form action="file.php"method="post">
<textarea name="code">Code goes here</textarea>
<input type="submit"value="submit">
</form>
write_file.php
<?php
// strip slashes before putting the form data into target file
$cd = stripslashes($_POST['code']);
// Show the msg, if the code string is empty
if (empty($cd))
echo "Nothing to write";
// if the code string is not empty then open the target file and put form data in it
else
{
$file = fopen("demo.php", "w");
echo fwrite($file, $cd);
// show a success msg
echo "data successfully entered";
fclose($file);
}
?>
This is a working script. be sure to change the url in the form action and the target file in fopen() function if you want to use it on your site.
In order to write to a file in PHP you need to go through the following steps:
Open the file
Write to the file
Close the file
$select = "data what we trying to store in a file";
$file = fopen("/var/www/htdocs/folder/test.txt", "a");
fwrite($file , $select->__toString());
fclose($file );
fwrite() is a smidgen faster and file_put_contents() is just a wrapper around those three methods anyway, so you would lose the overhead.
Article
file_put_contents(file,data,mode,context):
The file_put_contents writes a string to a file.
This function follows these rules when accessing a file.If FILE_USE_INCLUDE_PATH is set, check the include path for a copy of filename
Create the file if it does not exist then Open the file and Lock the file if LOCK_EX is set and If FILE_APPEND is set, move to the end of the file. Otherwise, clear the file content
Write the data into the file and Close the file and release any locks.
This function returns the number of the character written into the file on success, or FALSE on failure.
fwrite(file,string,length):
The fwrite writes to an open file.The function will stop at the end of the file or when it reaches the specified length,
whichever comes first.This function returns the number of bytes written or FALSE on failure.

Categories