Basic File Handling in PHP
Basic File Handling in PHP
File handling functions in PHP are extremely usefull and userfriendly. Many websites use simple text files as there data store because it has following advantages 1) Minimization of cost. Cost of maintaining databases like Oracle are huge, thus files are low cost answer to these databases. 2) Taking back Up of your database is very easy. All you have to do is to copy the file. 3) It much easier to transfer a text file from one OS to another. However there are divadvantages too 1) Text files do not support SQL Query languages. Thus you will have to code your data retrieval and updation algorithms yourself. 2) It does not use any indexing mechanism , thus searching mechanism is much slower. 3) You cannot use triggers, define primary keys , Foreign Keys etc. Now, lets start to see how PHP handles files. 1) Opening a file. In PHP you can open a file using the function call fopen ( "filename","mode") Here "mode" means whether you want to open the file in read mode, write mode or append mode. The values of this parameters are defined as
'r+' Open for reading and writing; place the file pointer at the beginning of the file. 'w' 'w+' 'a' 'a+'
'x'
Create and open for reading and writing; place the file pointer at the beginning of the file. If the file already exists, the fopen() call will fail by returning FALSE and generating an error of level 'x+' E_WARNING . If the file does not exist, attempt to create it. This is equivalent to specifying O_EXCL|O_CREAT flags for the underlying open(2) system call. This option is supported in PHP 4.3.2 and later, and only works for local files.
Example code for reading from a files <?php $file_name = "data.dat"; // absolute path : \home\data.dat $file_pointer = fopen($file_name, "r"); //Open the file in readonly mode, //check if you read permission in unix $file_read = fread($file_pointer, filesize($file_name)); echo $file_read; // Reading the file contents, through the pointer fclose($file_pointer); // close the file ?> Note: If the file resides in the some other folder than the php file then you have to give the full pathname. Now suppose fopen was unable to open the file then you may give user a message. Thus the code becomes <?php $file_name = "data.dat"; // absolute path : \home\data.dat $file_pointer = fopen($file_name, "r"); if (!$file_pointer) die ("could not open file $file_name"); //Open the file in readonly mode, //check if you read permission in unix $file_read = fread($file_pointer, filesize($file_name)); // Reading the file contents, through the pointer echo $file_read; // print the contents of the file; fclose($file_pointer); // close the file ?> Writing to a file: <?php $file_name = "data.txt"; $file_pointer = fopen($file_name, "w+"); // "w+" is the write mode, or the action we're going to perform on the file // "w+" mode clears the existing file content to 0 bytes fwrite($file_pointer, "PHP is power "); // write something to the file fclose($file_pointer); print "data written to file successfully"; ?> As you see whenever we open the file in write mode the previous contents are getting truncated. If you want to keep the previous file contents, then you have to open the file in "append" mode. Opening the file in append mode: <?php $file_name = "data.txt"; $file_pointer = fopen($file_name, "a"); // "a" is the append mode // "a" mode keeps the existing file content and starts writing from the end of the file
fwrite($file_pointer, "PHP is power "); // write something to the file fclose($file_pointer); print "data written to file successfully"; ?> With these basic basic knowledge of file handling we can try to perform some database maintenance operation through files. Suppose the name of your database file is "data.txt" and records are stored in the format
001 | Ravi | India \n 002 | Steve| Australia \n 003 | Paul | France \n 004 |Dustin|USA\n 005 |Jatin |India \n Printing all the records Now , if you want to print the employee information then the code will be <?php $filename = "data.txt"; $fp = fopen($filename, "r") or die("Couldn't open $filename"); while(!feof($fp)) { $line = fgets($fp); print "$line<br>"; } fclose($fp); ?> Searching a particuler record in a database file : Suppose you want to search the record of Ravi in the database. <?php $filename = "data.txt"; $fp = fopen($filename, "r") or die("Couldn't open $filename"); while(!feof($fp)) { $line = fgets($fp); if (preg_match('/Ravi/',$line)) // Print the line if it contains the word 'Ravi' print "$line<br>"; } fclose($fp); ?> Editing a record in database file Suppose you want to Edit the record of 'Steve' with the value 002 | Steve| Russia \n <?php $new_data = "002 | Steve| Russia \r\n";// "\r\n " is the line break $filename_original = "data.txt";
$filename_edited = "datacopy.txt" ; $fporiginal = fopen($filename_original, "r") or die("Couldn't open $filename_original"); $fpedited = fopen($filename_edited, "w") or die("Couldn't open $filename_edited"); while(!feof($fporiginal)) { $line = fgets($fporiginal); if (preg_match('/Steve/',$line)) // search the line if it contains the word 'Steve' fwrite($fpedited,$new_data); else fwrite($fpedited,$line); //if the line does not contain the word 'Steve' the write back the original line } fclose($fporiginal); fclose($fpedited); // now copy the contents of 'datacopy.txt' to 'data.txt' $filename_original = "data.txt"; $filename_edited = "datacopy.txt" ; $fporiginal = fopen($filename_original, "w+") or die("Couldn't open $filename_original"); $fpedited = fopen($filename_edited, "r") or die("Couldn't open $filename_edited"); $data = fread($fpedited, filesize($filename_edited)); fwrite($fporiginal ,$data); fclose($fporiginal); fclose($fpedited); unlink($filename_edited); //delete the file datacopy.txt ?> Deleteting a record from database file Suppose you want to delete the record of 'Steve'from the file , then the code will be <?php $filename_original = "data.txt"; $filename_edited = "datacopy.txt" ; $fporiginal = fopen($filename_original, "r") or die("Couldn't open $filename_original"); $fpedited = fopen($filename_edited, "w") or die("Couldn't open $filename_edited"); while(!feof($fporiginal)) { $line = fgets($fporiginal); if (!preg_match('/Steve/',$line)) // search the line if it contains the word 'Steve' fwrite($fpedited,$line); //if the line does not contain the word 'Steve' the write back the original line } fclose($fporiginal); fclose($fpedited); // now copy the contents of 'datacopy.txt' to 'data.txt' $filename_original = "data.txt"; $filename_edited = "datacopy.txt" ; $fporiginal = fopen($filename_original, "w+") or die("Couldn't open $filename_original"); $fpedited = fopen($filename_edited, "r") or die("Couldn't open $filename_edited"); $data = fread($fpedited, filesize($filename_edited)); fwrite($fporiginal ,$data); fclose($fporiginal); fclose($fpedited); unlink($filename_edited); //delete the file datacopy.txt ?>
In the above case when PHP writes to info.file for Rob, Bill also starts writing and at that instance when '\n' for Rob was still to be written. Causing a file sequence break! We don't want this happening, do we ? I'll take NO as the answer for the sake of progressing. So, let's look at file locking : <?php $file_name = "data.dat"; $file_pointer = fopen($file_name, "r"); $lock = flock($file_pointer, LOCK_SH); // I use 4.0.2 so LOCK_SH or you can use 1. if ($lock) { $file_read = fread($file_pointer, filesize($file_name)); $lock = flock($file_pointer, LOCK_UN); // Use 3 if < PHP4.0.2 } fclose($file_pointer); print "file contents are $file_read"; ?gt; In the above if 2 files read.php and read2.php access the file then both of them will be able to read it, but incase a program needs to write to the file it will have to wait till the read operation finishes and the lock is released. <?php $file_name = "data.dat"; $file_pointer = fopen($file_name, "w"); $lock = flock($file_pointer, LOCK_EX); // Use 2 if you use < PHP4.0.2 if ($lock) { fwrite($file_pointer, "what u wanna write"); flock($file_pointer, LOCK_UN); // Use 3 < PHP4.0.2 } fclose($file_pointer); print "data written to file successfully"; ?gt;
Though using "w" is only used for overwriting data and to me can't be put to practical use! <?php $file_name = "data.dat"; $file_pointer = fopen($file_name, "a"); $lock = flock($file_pointer, LOCK_EX); // Use 2 if you use < PHP4.0.2 if ($lock) { fseek($file_pointer, 0, SEEK_END); // Use this if < PHP4.0RC1 : fseek($file_pointer, filsize($file_name)); fwrite($file_pointer, "what u wanna write"); flock($file_pointer, LOCK_UN); // Use 3 < PHP4.0.2 } fclose($file_pointer); print "data written to file successfully"; ?gt; Hmmm... something different in appending data, yes FSEEK! It's always good to make sure that the file writing cursor is at the end of the file. For doing all this in windows, just escape the file names with a '\'. MISC NOTES ABOUT FLOCK : Flock() locks the file only after the file has been opened. So incase at instance A the file was opened and at instance A.5 the lock was obtained. Now the file contents are the contents that were present at instance A and not when the other program finished whatever (appending assumed). Hence fseek should always be used not only in appending but also when reading file contents.