Use PHP to implement a file management system
/**
* @] Class Name [= IO
* @] Class URI [= System. IO
* @] Purpose [=
* This class is used to process the file system.
* @] Author [= snail kedevil <51JS, BU, PHPx> (snakevil@qq.com)
* @] Version [= 1.1.1
* @] Create [= 17:13 2004-3-25
* @] Modifications [=
* 4:04 2004-3-30"
* + Fixed some bugs in the generate_path () method.
* + Redesign Method no_comment ()
* 4:32 2004-3-29
* + Simplified method list_dir () return value [
* + Added the file_info () method to obtain the file or directory information.
* Pm
* + Sort out Optimization Algorithms
*
* + Abstract error handling to petabytes
* + Added the no_comment () method to delete the C Standard comment in the file.
* @] See [=
*/
Class IO extends SnkClass
Var $ result; // The result returned by the operation. If the return value of the method is mixed, the successful operation result can be obtained here.
Var $ exec_cmd; // execution method, which is not applied
Var $ exist_dir; // The Last directory that exists when the directory is created. It is used for copy () and move ()
Var $ buffer_size; // the size of the file read buffer, which is modified based on the service application size and server configuration. The default value is recommended.
Function IO ()
Parent: SnkClass ();
$ This-> result = array ();
$ This-> exec_cmd = "";
$ This-> exist_dir = "";
$ This-> buffer_size = 8192;
Return $ this;
}
/**
* @] Method Name [= list_dir ()
* @] Purpose [=
* Reads the content of a specified directory and returns an array of content.
* @] Parameter [=
* String $ dir_path specifies the directory path. The default value is the current directory.
* @] Return [= mixed error: FALSE; otherwise, FALSE is returned.
* Array (
* Array ("name", "location", "type "),
*......
*)
* @] Author [= snail kedevil <51JS, BU, PHPx> (snakevil@qq.com)
* @] See [=
*/
Function list_dir ($ path = ".")
If (! Is_dir ($ path) return $ this-> error_occur (0x000B, _ FUNCTION __);
If (! Is_readable ($ path) return $ this-> error (0x0002, $ path );
$ Dh = @ opendir ($ path );
$ Result = array ();
$ Path = realpath ($ path );
If ($ path [strlen ($ path)-1]! = DIRECTORY_SEPARATOR) $ path. = DIRECTORY_SEPARATOR; // ensure that the absolute directory address is followed by a directory Separator
While (FALSE! ==( $ Fh = readdir ($ dh) {// use! = Prevent processing files and directories with names 0 or FALSE
If ($ fh = "." | $ fh = "..") continue; // ignore a specific system folder
$ I = $ path. $ fh; // get the absolute address
$ T = array (
"Name" => $ fh, V u,
"Location" => $ I,
"Type" => is_file ($ I )? 1: (is_dir ($ I )? 0:-1)
);
$ Result [] = $ t;
}
Closedir ($ dh );
Unset ($ dh, $ fh, $ t, $ I );
Clearstatcache (); // clear the file system cache
Return $ this-> result = $ result;
}
/**
* @] Method Name [= file_info ()
* @] Purpose [=
* Obtain the attributes of a specified file or directory.
* @] Parameter [=
* String $ dir_path specifies the directory path. The default value is the current directory.
* @] Return [= mixed error: FALSE; otherwise, FALSE is returned.
* Array ("name", "location", "type", "size", "access", "change", "modify", "read", "write "),
* @] Author [= snail kedevil <51JS, BU, PHPx> (snakevil@qq.com)
* @] See [=
*/
Function file_info ($ path = ".")
$ Path = realpath ($ path );
If (! $ Path) return $ this-> error_occur (0x000A, _ FUNCTION __);
$ Result = array (
"Name" => substr ($ path, strrpos ($ path, DIRECTORY_SEPARATOR) + 1 ),
"Location" => $ path, FHHC ,~ | 5
"Type" => is_file ($ path )? 1: (is_dir ($ path )? 0:-1 ),
"Size" => filesize ($ path ),
"Access" => fileatime ($ path ),
"Modify" => filemtime ($ path ),
"Change" => filectime ($ path ),
"Read" => is_readable ($ path ),
"Write" => is_writeable ($ path)
);
Clearstatcache ();
Return $ this-> result = $ result;
}
/**
* @] Method Name [= seek file ()
* @] Purpose [=
* Based on Regular Expression Conditions, search for matched files and directories in the corresponding directory and sub-directories at a given level
* @] Parameter [=
* String $ pattern is compatible with PERL standard regular expressions to specify search matching requirements./^ $/is added .*
* String $ path: directory path to be searched. The default value is the current path.
* Enum $ seesk_type has three possible values:-1 0 1, 0 for folders, 1 for files, and-1 for both. The default value is 1.
* Int $ sub_dir indicates the depth of the subdirectory to be searched. If the specified directory is not counted, it is recommended that the value not exceed 5. The default value is
* Limit $ limit on search results to avoid excessive waste of system resources. The default value is 100.
* @] Return [= mixed error returns FALSE; otherwise
* Array (
* Array (
* "Name", "locate", "type"
*),
*......
*)
* @] Author [= snail kedevil <51JS, BU, PHPx> (snakevil@qq.com)
* @] See [=
*/
Function seek_file ($ pattern = ". *", $ path = ".", $ seek_type = 1, $ sub_dir_level = 0, $ limit = 100)
/* Check the parameter value */
$ Is_error = $ seek_type! = 1 & $ seek_type! = 0 & $ seek_type! =-1;
$ Is_error = $ is_error &&(! Is_int ($ sub_dir_level) | $ sub_dir_level <0 );
$ Is_error = $ is_error &&(! Is_int ($ limit) | $ limit <1 );
If ($ is_error) return $ this-> error_occur (0x000B, _ FUNCTION __);
Unset ($ is_error );
$ Result = array ();
/* Array () = FALSE, so use = */
If (FALSE = $ I = $ this-> list_dir ($ path) return FALSE; // if the directory cannot be listed, return
For ($ j = 0, $ k = count ($ I); $ j <$ k; $ j ++ ){
If ($ I [$ j] ["type"] =-1) continue; // for non-directory non-file projects, skip
If ($ I [$ j] ["type"] = 0 & $ sub_dir_level) {// if You Need To search for a lower-level directory
If (FALSE ===$ l = $ this-> seek_file ($ pattern, $ I [$ j] ["location"], $ seek_type, ($ sub_dir_level-1 ), $ limit) return FALSE;
$ Result = array_merge ($ result, $ l); // Add the search result of the lower-level directory
}
If ($ seek_type + $ I [$ j] ["type"] = 1 |! Preg_match ("/^". $ pattern. "$/", $ I [$ j] ["name"]) continue; // skip this step if you do not search for the current type
$ Result [] = $ I [$ j];
If (count ($ result) >=$ limit) {// beyond the required length, leave the list
Array_splice ($ result, $ limit );
Break;
}
}
Unset ($ I, $ j, $ k, $ l );
Return $ this-> result = $ result;
}
/**
* @] Method Name [= delete ()
* @] Purpose [=
* Delete a specified object, file, or folder-including non-empty folders of the inner directory and file
* @] Parameter [=
* String $ path specifies the path of the content to be deleted, either file or directory.
* @] Return [= boolean: FALSE is returned; otherwise, TRUE is returned.
* @] Author [= snail kedevil <51JS, BU, PHPx> (snakevil@qq.com)
* @] See [=
*/
Function delete ($ path = ""){
$ Path = realpath ($ path );
If (! $ Path) return $ this-> error_occur (0x000A, _ FUNCTION __);
If (! Is_dir ($ path )){
If (@ unlink ($ path) return TRUE; // The object is successfully deleted.
Return $ this-> error_occur (0x0004, $ path );
} Else {
If (FALSE = $ I = $ this-> list_dir ($ path) return FALSE; // you cannot list directories.
For ($ j = 0, $ k = count ($ I); $ j <$ k; $ j ++)
If (! $ This-> delete ($ I [$ j] ["location"]) return FALSE; // An error occurred while deleting the directory content.
Unset ($ I, $ j, $ k );
Return TRUE;
}
}
/**
* @] Method Name [= generate_path () = l
* @] Purpose [=
* Obtain the absolute address of an existing or non-existing file or directory.
* @] Parameter [=
* String $ path: the current relative and absolute address of the file and directory to obtain the address
* @] Return [= address obtained by string
* @] Author [= snail kedevil <51JS, BU, PHPx> (snakevil@qq.com)
* @] See [=
*/
Function generate_path ($ path = ""){
$ I = "/" = DIRECTORY_SEPARATOR? "\": "/"; // Unified directory delimiter
$ Path = str_replace ($ I, DIRECTORY_SEPARATOR, strval ($ path ));
If ($ path [strlen ($ path)-1]! = DIRECTORY_SEPARATOR) $ path. = DIRECTORY_SEPARATOR;
$ I = strpos ($ path, DIRECTORY_SEPARATOR); // obtain the location of the first directory delimiter in the path
$ Ext = substr ($ path, $ I + 1 );
$ Path = substr ($ path, 0, $ I + 1 );
If ($ I = realpath ($ path) $ path = $ I; // obtain the basic path.
Else {
$ Ext = $ path. $ ext;
$ Path = realpath (".");
}
If (strlen ($ ext) {// process the Remaining Content
$ Ext = preg_replace ("/[\:\*\? \ "\ <\> \ |]/", "", Explode (DIRECTORY_SEPARATOR, $ ext ));
Array_pop ($ ext );
$ Path = explode (DIRECTORY_SEPARATOR, $ path); // create a directory layer axis
If ($ path [count ($ path)-1] = "") array_pop ($ path );
While (count ($ ext )){
$ I = array_shift ($ ext );
If ($ I = ".." & count ($ path)> 1) array_pop ($ path );
Elseif (""! = Str_replace (".", "", $ I) $ path [] = $ I;
}
$ Path = implode (DIRECTORY_SEPARATOR, $ path );
}
Unset ($ ext, $ I );
Return $ path;
}
/**
* @] Method Name [= make_dir ()
* @] Purpose [=
* Any folder can be created, either in relative or absolute paths, or in deep layers.
* @] Parameter [=
* String $ path: the final directory path to be created
* @] Return [= boolean: FALSE is returned; otherwise, TRUE is returned.
* @] Author [= snail kedevil <51JS, BU, PHPx> (snakevil@qq.com)
* @] See [=
*/)
Function make_dir ($ path = ""){
$ I = explode (DIRECTORY_SEPARATOR, $ this-> generate_path ($ path); // generate a directory path
$ Path = array_shift ($ I );
For ($ j = 0, $ k = count ($ I); $ j <$ k; $ j ++ ){
$ Path. = DIRECTORY_SEPARATOR. $ I [$ j];
If (! Is_dir ($ path )){
If ($ this-> exist_dir = "") $ this-> exist_dir = $ path; // record the last directory path
If (! @ Mkdir ($ path) return $ this-> error_occur (0x0003, substr ($ path, 0, strrpos ($ path, DIRECTORY_SEPARATOR )));
}
}
If ($ this-> exist_dir = "") $ this-> exist_dir = $ path;
Return TRUE;
}
/**
* @] Method Name [= verify_file ()
* @] Purpose [=
* Use the MD5 Algorithm to compare whether the two files are the same
* @] Parameter [=
* String $ src Source File Path
* String $ dst destination file path
* Boolean $ interal for files larger than 1 MB, setting FALSE saves MD5 verification steps and reduces server load
* @] Return [= boolean: FALSE is returned; otherwise, TRUE is returned.
* @] Author [= snail kedevil <51JS, BU, PHPx> (snakevil@qq.com)
* @] See [=
*/
Function verify_file ($ src = "", $ dst = "", $ interal = TRUE ){
If (! Is_file ($ src) |! Is_file ($ dst) return $ this-> error_occur (0x000B, _ FUNCTION __);
If (! Is_readable ($ src) return $ this-> error (0x0006, $ src );
If (! Is_readable ($ dst) return $ this-> error (0x0006, $ dst );
$ I = filesize ($ src );
If (filesize ($ dst )! = $ I) {// File Size
Unset ($ I );
Return FALSE;
}
If ($ I> 1024*1024*1024 &&! $ Interal) {// for 1 MB files, skip
Unset ($ I );
Return TRUE;
}
Unset ($ I );
If (md5_file ($ src )! = Md5_file ($ dst) return FALSE; // file MD5 verification does not match, and the content is different
Return TRUE;
}
/**
* @] Method Name [= copy ()
* @] Purpose [=
* Any folder or file can be copied with a relative or absolute path. After the file is copied, the system checks whether the error data is correct.
* @] Parameter [=
* String $ src_path specifies the path of the source content to be copied, either file or directory
* String $ dst_path specifies the path of the target content to be copied, which can be a file or directory. The attribute is determined by $ src_path. It can be a lower-level directory of $ src_path.
* @] Return [= boolean: FALSE is returned; otherwise, TRUE is returned.
* @] Author [= snail kedevil <51JS, BU, PHPx> (snakevil@qq.com)
* @] See [=
*/
Function copy ($ src = "", $ dst = "", $ sub = FALSE ){
If (! $ Src = realpath ($ src) return $ this-> error_occur (0x000B, _ FUNCTION __);
$ Dst = $ this-> generate_path ($ dst );
If (is_dir ($ src) {// process directory
/*
* Algorithm Description:
* I was going to use a simple recursive algorithm. When I met the gods and the demons, I found a problem: if the target path
* What should I do if it is the descendant path of the Source Path? In this way, the algorithm will continue to be tested...
* The $ this-> exist_dir attribute is added to record the existing part of the target path in this case. So a new question
* Question: how to save this attribute?
* To integrate the entire function into the $ this-> copy () method, you must record it in this function.
*, So another effective method is required to prevent the changes in each operation.
* As a work und, the hidden parameter $ sub is always at the most of the parameter table as long as the algorithm remains unchanged.
* The last one. As a result, the method becomes unstable at the beginning, but there is no way to do this. You can only hope that the programmer will not intentionally destroy it.
* Write $ this-> exist_dir for external calls because the default value is FALSE. Explicit TRUE in internal recursion,
* This attribute ensures validity.
*/
If (! Is_readable ($ src) return $ this-> error (0x0002, $ src );
If ($ dst [strlen ($ dst)-1]! = DIRECTORY_SEPARATOR) $ dst. = DIRECTORY_SEPARATOR;
If (TRUE = $ sub & $ src = $ this-> exist_dir) return TRUE; // The Source Path is the recorded target path.
If (TRUE! ==$ Sub) $ this-> exist_dir = ""; // record the directory path existing in the target directory before creating the Directory
If (! $ This-> make_dir ($ dst) return FALSE; // create a directory
If (FALSE = $ I = $ this-> list_dir ($ src) return FALSE; // An error occurred while reading the directory.
For ($ j = 0, $ k = count ($ I); $ j <$ k; $ j ++) if (! $ This-> copy ($ I [$ j] ["location"], $ dst. $ I [$ j] ["name"], TRUE) return FALSE;
Unset ($ I, $ j, $ k );
Return true;
} Else {
If (! Is_readable ($ src) return $ this-> error (0x0006, $ src );
If ($ this-> verify_file ($ src, $ dst) return TRUE;
If (! Copy ($ src, $ dst) return $ this-> error_occur (0x0007, $ dst );
If (! $ This-> verify_file ($ src, $ dst )){
@ Unlink ($ dst); // failed to copy the file and delete the new file
Return $ this-> error_occur (0x0007, $ dst );
}
Return TRUE;
}
}
/**
* @] Method Name [= move ()
* @] Purpose [=
* Move any folder or file. The relative or absolute path is acceptable. After the file is moved, verify whether the error data is incorrect. www.hidianying.cn
* @] Parameter [=
* String $ src_path specifies the path of the source content to be moved, either file or directory
* String $ dst_path specifies the path of the target content to be moved, which can be a file or directory. Its nature is determined by $ src_path. It can be a lower-level directory of $ src_path.
* @] Return [= boolean: FALSE is returned; otherwise, TRUE is returned.
* @] Author [= snail kedevil <51JS, BU, PHPx> (snakevil@qq.com)
* @] See [=
*/
Function move ($ src = "", $ dst = "", $ sub = FALSE ){
If (! $ Src = realpath ($ src) return $ this-> error_occur (0x000B, _ FUNCTION __);
$ Dst = $ this-> generate_path ($ dst );
If (is_dir ($ src) {// process directory
If (! Is_readable ($ src) return $ this-> error (0x0002, $ src );
If ($ dst [strlen ($ dst)-1]! = DIRECTORY_SEPARATOR) $ dst. = DIRECTORY_SEPARATOR;
If (TRUE ===$ sub & $ src = $ this-> exist_dir) return TRUE;
If (TRUE! ==$ Sub) $ this-> exist_dir = "";
If (! $ This-> make_dir ($ dst) return FALSE;
If (FALSE = $ I = $ this-> list_dir ($ src) return FALSE;
For ($ j = 0, $ k = count ($ I); $ j <$ k; $ j ++) if (! $ This-> move ($ I [$ j] ["location"], $ dst. $ I [$ j] ["name"], TRUE) return FALSE;
Unset ($ I, $ j, $ k );
If (FALSE === strpos ($ this-> exist_dir, $ src ))
If (! @ Rmdir ($ src) return $ this-> error_occur (0x0004, $ src); // Delete the upper directory of the non-target directory
Return TRUE;
} Else {
If (! Is_readable ($ src) return $ this-> error (0x0006, $ src );
If ($ this-> verify_file ($ src, $ dst) return TRUE;
If (! Copy ($ src, $ dst) return $ this-> error_occur (0x0007, $ dst );
If (! $ This-> verify_file ($ src, $ dst) {M
@ Unlink ($ dst );
Return $ this-> error_occur (0x0007, $ dst );
}
If (! @ Unlink ($ src) return $ this-> error_occur (0x0006, $ src); // Delete the source file
Return TRUE;
}
}
/**
* @] Method Name [= no_comment ()
* @] Purpose [=
* Clear comments of the C specification in the file
// This tutorial comes from 97xxoo tutorial Network (www.97xxoo.org) to view the complete tutorial, please click: http://www.97xxoo.org/article/1/2008/20081018053.shtml
* @] Parameter [=
* String $ path specifies the object to be operated
* @] Return [= boolean: FALSE is returned; otherwise, TRUE is returned.
* @] Author [= snail kedevil <51JS, BU, PHPx> (snakevil@qq.com)
* @] See [=
*/
Function no_comment ($ path = ""){
If (! Is_file ($ path) return $ this-> error_occur (0x000B, _ FUNCTION __);
If (! Is_readable ($ path) return $ this-> error (0x0006, $ path );
If (! Is_writeable ($ path) return $ this-> error (0x0007, $ path );
If (! $ Th = tmpfile () return $ this-> error_occur (0x000C, $ path); // create a temporary file
$ Fh = fopen ($ path, "r + B ");
If (! Flock ($ fh, LOCK_EX) {// lock the file
Fclose ($ fh );
Unset ($ fh );
Return $ this-> error_occur (0x0009, $ path );
}
$ Fbuffer = fread ($ fh, $ this-> buffer_size * 2); // file read buffer
$ Tbuffer = ""; // Temporary File Buffer <
$ In_dq = $ in_sq = $ in_lc = $ in_bc = FALSE;
While ($ fblen = strlen ($ fbuffer) {// process raw data
$ Fstats = feof ($ fh );
For ($ I = 0; $ I <$ fblen; $ I ++) {// analyze the File Content
If (! $ Fstats & $ I + 5> $ fblen) break; // when the file is not fully read, the neighboring buffer reads the content of the next file.
$ J = substr ($ fbuffer, $ I, 2 );
$ K = $ j [0];
If ($ j = "/*"&&! $ In_dq &&! $ In_sq &&! $ In_lc) {// It is not in the string or line comment. The block comment starts.
$ In_bc = TRUE;
$ I ++;
} Elseif ($ j = "*/" & $ in_bc) {// the end of the block comment
$ In_bc = FALSE;
$ I + = 2;
} Elseif ($ j = "//"&&! $ In_dq &&! $ In_sq &&! $ In_bc) {// start the line comment
$ In_lc = TRUE;
$ I ++;
} Elseif ($ in_lc & ($ k = "\ r" | $ k = "\ n") $ in_lc = FALSE; // end of line comment
Elseif ($ j = "\\\\" | $ j = "\\\" "| $ j = "\\'") {// escape characters)
$ Tbuffer. = $ j;
$ I ++;
Continue;
} Elseif ($ k = "\""&&! $ In_sq &&! $ In_bc &&! $ In_lc) $ in_dq =! $ In_dq; // double quotation mark string start and end
Elseif ($ k = "'"&&! $ In_dq &&! $ In_bc &&! $ In_lc) $ in_sq =! $ In_sq; // start and end of a single quotation mark string
If ($ in_lc | $ in_bc) continue; // in the comment, skip
$ Tbuffer. = $ fbuffer [$ I];
}
$ Fbuffer = substr ($ fbuffer, $ I); // discard the read part.
Unset ($ I, $ j, $ k );
If (! $ Fstats) $ fbuffer. = fread ($ fh, $ this-> buffer_size );
If ($ fstats | strlen ($ tbuffer) >=$ this-> buffer_size) {// write legal data to a temporary file
If (! Fwrite ($ th, $ tbuffer) {// write failed, insufficient space
Fclose ($ th );
Flock ($ fh, LOCK_UN );
Fclose ($ fh );
Unset ($ th, $ fh, $ in_dq, $ in_sq, $ in_lc, $ in_bc, $ I, $ j, $ k );
Return $ this-> error_occur (0x000D ,"");
}
$ Tbuffer = "";
}
}
Unset ($ fbuffer, $ tbuffer, $ fstats, $ in_dq, $ in_sq, $ in_lc, $ in_bc );
Rewind ($ fh); // moves the file pointer back to the beginning of the file
Rewind ($ th );
$ I = $ j = "";
$ K = 0;
While (! Feof ($ th) {// write the temporary file data back to the source file
$ I = fgets ($ th, $ this-> buffer_size );
If ($ j = "") {// get the line break of the file system
$ J = substr ($ I,-2 );
If ($ j = "\ r \ n ")
Elseif ($ j [1] = "\ r" | $ j [1] = "\ n ")
$ K = 1;
$ J = $ j [1];
} Else $ j = "";
}
If (substr ($ I,-$ k) = $ j ){
$ I = rtrim (substr ($ I, 0,-$ k), "\ t ");
If (strlen ($ I) fwrite ($ fh, $ I. $ j); // clear the right space
Else continue;
} Else fwrite ($ fh, rtrim ($ I, "\ t "));
}
Fflush ($ fh); // save and close the file
Ftruncate ($ fh, ftell ($ fh ));
Fclose ($ th );
Flock ($ fh, LOCK_UN );
Fclose ($ fh );
Unset ($ I, $ j, $ k, $ fh, $ th );
Return TRUE;
}
}
/**
* @] Error List [=
* 0x0001 the specified directory does not exist
* 0x0002 the specified directory has no read permission.
* 0x0003 the specified directory has no write permission
* 0x0004 the specified directory does not have the delete permission.
* 0x0005 the specified file does not exist
* 0x0006 the specified file has no read permission.
* 0x0007 the specified file has no write permission
* 0x0008 the specified file does not have the delete permission.
* 0x0009 the specified file cannot be locked
* 0x000A the specified object does not exist.
* The parameter specified by 0x000B is incorrect.
* 0x000C cannot create temporary files
* 0x000D insufficient disk space
* 0x000E
* 0x000F
* 0x0010
* 0x0011
*
*/
?>