Use PHP to implement a file management system

Source: Internet
Author: User
Tags flock rewind

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

*

*/

?>

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.