PHP
/ *
*
* =========== z ==================
* QQ: 118824
* MSN: Snakevil_@hotmail.com
* Hp: http://www.snakevil.com/
* =========== z ==================
*
* /
/ **
* @] Class name [= IO
* @] Class Uri [= System.io
* @] Purpose [=
* This class is used to process the file system
* @] Author [= snakevil <51js, bu, phpx> (snakevil@qq.com)
* @] Version [= 1.1.1
* @】 Create [= 17:13 2004-3-25
* @] Modifications [=
* 4:04 2004-3-30
* Some bugs existing in the generate_path () method
* Redesign method NO_COMMENT ()
* 4:32 2004-3-29
* Simplified method List_dir () return value
* Increase method file_info () Get file or directory information
* 5:35 2004-3-28
* Finishing optimization algorithm
* 7:31 2004-3-27
* Abstract as base class
* Increase method no_comment () Delete file in C specification notes
* @] See [=
* /
Class Io extends snkclass {
VAR $ result; // Operation returns, if the method returns value Mixed, the successful operation result can be obtained here.
Var $ exec_cmd; // Execute method, not applying it for the time being
VAR $ exist_dir; // Create the directory of the current directory, currently Copy () and Move ()
VAR $ buffer_size; // File read buffer size, according to the service application size and server configuration modification, it is recommended to default
Function IO () {
Parent :: snkclass ();
$ this-> Result = array ();
$ this-> EXEC_CMD = ""
$ this-> EXIST_DIR = ""
$ this-> buffer_size = 8192;
Return $ THIS;
}
/ **
* @] Method name [= list_dir ()
* @] Purpose [=
* Read the specified directory content, return to the content array
* @] Parameter [=
* String $ dir_path Specifies the directory path, default is the current directory
* @] Return [= MIXED error Returns false, otherwise returns
* Array
* Array ("Name", "Location", "Type"), * ...
*)
* @] Author [= snakevil <51js, bu, phpx> (snakevil@qq.com)
* @] See [=
* /
Function List_Dir ($ PATH = ") {
IF (! is_dir ($ PATH)) Return $ this-> Error_occur (0x000B, __Function__);
IF (! is_readable) Return $ this-> Error_occur (0x0002, $ PATH);
$ DH = @opendir ($ PATH);
$ result = array ();
$ PATH = RealPath ($ PATH);
IF ($ PATH [Strlen ($ PATH) -1]! = DIRECTORY_SEPARATOR) $ PATH. = Directory_seParetor; / / Guarantee Directory Absolute Address After Directory Separator
While (false! == ($ fH = readir ($ dh))) {// Use! == Prevent file, directory, directory, directory
IF ($ fH == "." | $ fh == "..") Continue; // ignore the system specific folder
$ I = $ PATH. $ fH; // Get absolute address
$ T = array (
"name" => $ fh,
"Location" => $ i,
"type" => is_file ($ i)? 1: (is_dir ($ i)? 0: -1)
);
$ result [] = $ t;
}
CloseDir ($ DH);
Unset ($ DH, $ FH, $ T, $ I);
ClearsTatCache (); // Clear file system cache
Return $ this-> Result = $
}
/ **
* @] Method Name [= file_info ()
* @] Purpose [=
* Get the properties of the specified file or directory
* @] Parameter [=
* String $ dir_path Specifies the directory path, default is the current directory
* @] Return [= MIXED error Returns false, otherwise returns
* Array ("Name", "Location", "Type", "Size", "Access", "Change", "Modify", "Read", "WRITE"),
* @] Author [= snakevil <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, STRPOS ($ PATH, DIRECTORY_SEPARATOR) 1), "location" => $ PATH,
"Type" => is_file ($ PATH)? 1: (is_dir ($ PATH)? 0: -1),
"size" => FileSize ($ PATH),
"Access" => FileAtime ($ PATH),
"Modify" => filemtime ($ PATH),
"Change" => filectime ($ PATH),
"r" => is_readable ($ PATH),
"Write" => is_writeable ($ PATH)
);
ClearsTatcache ();
Return $ this-> Result = $
}
/ **
* @] Method name [= seek_file ()
* @] Purpose [=
* Search in the corresponding directory and the subdirectory of the corresponding directory and a subdirectory of the given level in the corresponding directory, the directory
* @] Parameter [=
* String $ Pattern Compatible regular expressions indicate that the search match requires / ^ $ /, the default. *
* String $ Path for searching directory path, default is the current path
* ENUM $ SEESK_TYPE has -1 0 1 three possible values, 0 only folders, 1 file, -1 includes, default is 1
* INT $ sub_dir search for subdirectory depth, specified directory is not, it is recommended not to exceed 5, default is 0
* LIMIT $ limited to search results restriction, avoid excessive waste system resources, default is 100
* @] Return [= Mixed error Returns false, otherwise
* Array
* Array
* "Name", "Locate", "TYPE"
*),
* ...
*)
* @] Author [= snakevil <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 * /
$ I_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 ($ limited) || $ limited <1);
IF ($ is_ERROR) RETURN $ this-> Error_occur (0x000b, __function __); unset ($ is_ERROR);
$ result = array ();
/ * Array () == FALSE, so you need to use === * /
IF (false === $ i = $ this-> list_dir ($ PATH)) Return False; // If you cannot list the directory, return
For ($ j = 0, $ k = count ($ i); $ j <$ k; $ j ) {
IF ($ I [$ J] ["Type"] == - 1) Continue; // Skip for non-catalog non-file items
IF ($ I [$ J] ["Type"] == 0 && $ SUB_DIR_LEVEL) {// If you need to search the underlying 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 underlying directory search result
}
IF ($ seek_type $ i [$ j] == 1 ||! preg_match ("/^"" $ Pattern. "$ /", $ i [$ j] ["name"]) Continue ; // If you do not search for the current type, skip
$ Result [] = $ i [$ j];
IF (count ($ result)> = $ limit) {// Close the length of the required length, leave the list
Array_SPLICE ($ RESULT, $ LIMIT);
Break;
}
}
UNSET ($ I, $ J, $ K, $ L);
Return $ this-> Result = $
}
/ **
* @] Method name [= delete ()
* @] Purpose [=
* Delete Specify objects, files, or folders - Non-empty folders including introns and files
* @] Parameter [=
* String $ PATH Specifies the content path, file or directory you want to delete
* @] Return [= Boolean error Returns false, otherwise TRUE
* @] Author [= snakevil <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) return true; // file deletion success
Return $ this-> Error_occur (0x0004, $ PATH);
} Else {
IF (false === $ i = $ this-> list_dir ($ PATH)) Return False; // cannot list the directory
For ($ J = 0, $ K = Count ($ i); $ J <$ K; $ J ) IF (! $ this-> Delete ($ I [$ J] ["Location"]) Return False; // Delete the contents of the directory error
UNSET ($ I, $ J, $ K);
Return True;
}
}
/ **
* @] Method name [= generate_path ()
* @] Purpose [=
* Get the absolute address of the existing or not existing files, directory
* @] Parameter [=
* String $ path To get the file file, the directory existing relative, absolute address
* @] Return [= String the address obtained
* @] Author [= snakevil <51js, bu, phpx> (snakevil@qq.com)
* @] See [=
* /
Function generate_path ($ PATH = ") {
$ I = "/" == DIRECTORY_SEPARATOR? "//": "/"; // Unified directory split
$ PATH = STR_REPLACE ($ I, Directory_separator, Strval ($ PATH));
IF ($ PATH [Strlen ($ PATH) -1]! = Directory_seParetor) $ path. = Directory_sePare;
$ I = STRPOS ($ PATH, DIRECTORY_SEPARATOR); // Get position of the first directory split in the path
$ ext = SUBSTR ($ PATH, $ I 1);
$ PATH = SUBSTR ($ PATH, 0, $ I 1);
IF ($ I = realpath) $ PATH = $ i; // Get the basic path
Else {
$ ext = $ Path. $ ext;
$ PATH = RealPath (".");
}
IF (Strlen) {// Treatment of the remaining content
$ ext = preg_replace ("/> / |] /", ",", ", explode (Directory_seParetor, $ ext));
Array_POP ($ ext);
$ PATH = EXPLODE (Directory_seParetor, $ PATH); // Set the catalog layer shaft
IF ($ Path [count ($ PATH) -1] == "" "Array_POP ($ PATH);
While (count) {
$ i = array_shift ($ ext);
IF ($ I == "." && Count> 1) Array_POP ($ PATH);
Elseif (""! = Str_replace (".", ", $ i)) $ path [] = $ i;
}
$ PATH = IMPLODE (Directory_seParetor, $ PATH);
}
UNSET ($ EXT, $ I);
Return $ PATH;
}
/ **
* @] Method name [= make_dir ()
* @] Purpose [=
* Establish any folder, the relative or absolute path, the deep construction can also
* @] Parameter [= * string $ path to create the final directory path
* @] Return [= Boolean error Returns false, otherwise TRUE
* @] Author [= snakevil <51js, bu, phpx> (snakevil@qq.com)
* @] See [=
* /
Function make_dir ($ PATH = "") {
$ i = evPlode (Directory_seParetor, $ this-> generate_path ($ PATH)); // Generate Directory Path
$ PATH = Array_shift ($ I);
For ($ j = 0, $ k = count ($ i); $ j <$ k; $ j ) {
$ PATH. = Directory_seParetor. $ i [$ j];
IF (! is_dir ($ PATH)) {
IF ($ this-> EXIST_DIR == ") $ this-> EXIST_DIR = $ path; // Record the last existing directory path
If (! @mkdir ($ PATH)) Return $ this-> Error_occur (0x0003, Substr ($ PATH, 0, STRPOS ($ PATH, DIRECTORY_SEPARATOR));
}
}
IF ($ THIS-> EXIST_DIR == ") $ this-> EXIST_DIR = $ PATH;
Return True;
}
/ **
* @] Method Name [= verify_file ()
* @] Purpose [=
* Compare two files with the same MD5 algorithm
* @] Parameter [=
* String $ src source file path
* String $ DST target file path
* Boolean $ INTERAL For more than 1MB file, set False to save the MD5 inspection step, reduce server burden
* @] Return [= Boolean error Returns false, otherwise TRUE
* @] Author [= snakevil <51js, bu, phpx> (snakevil@qq.com)
* @] See [=
* /
Function Verify_File ($ SRC = ", $ dst =", $ interaal = true) {
IF (! is_file ($ src) ||! is_file ($ dst)) Return $ this-> error_occur (0x000b, __function__);
IF (! is_readable ($ src)) Return $ this-> Error_occur (0x0006, $ SRC);
IF (! is_readable ($ dst)) Return $ this-> Error_occur (0x0006, $ dst);
$ I = FileSize ($ src);
IF (filesis ($ dst)! = $ i) {// file size is not equal
UNSET ($ I);
Return False;
}
IF ($ I> 1024 * 1024 * 1024 &&! $ interaal) {// For 1MB file, if you do not ask for accurate check, skip
UNSET ($ I);
Return True;
}
UNSET ($ I);
IF (MD5_FILE ($ src)! = md5_file ($ dst)) Return False; // The file MD5 test does not match, and the content is different Return True;
}
/ **
* @] Method name [= Copy ()
* @] Purpose [=
* Copying, files, files, relative, or absolute paths, will be checked, check if the error data is wrong after the file replication is completed.
* @] Parameter [=
* String $ src_path Specifies the source path, file or directory you want to copy
* String $ dst_path Specifies that the target content path, file or directory you want to copy can be determined by $ src_path, which can be the next directory of $ src_path
* @] Return [= Boolean error Returns false, otherwise TRUE
* @] Author [= snakevil <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)) {// Processing Directory
/ *
* About the algorithm:
* Originally intended to use a very simple recursive algorithm, encounter God, encounter a magic, and then discovered a question: if the target path
* What should I do with the post-generation path of the source path? This way, the law will continue to detect ...
* The $ this-> EXIST_DIR property is added to record the part of the target path in this case. So the new question
* Question: How to save this property?
* Integrate the entire function to $ this-> copy () method, then you must record $ this-> exist_dir in this function.
* Changes, there is a need for an additional effective way to block changes to them in each operation.
* As a change, I use hidden parameters $ SUB, this parameter is in any case, as long as the algorithm is constant, always in the parameter table
* last one. Therefore, the method has begun to become unstable, but there is no way, you can only want the programmer to not deliberately destroy.
* Write $ this-> exist_dir when calling because of the default false. During internal recursive, dominant TRUE, no
* This property guarantees effectiveness.
* /
IF (! is_readable ($ src)) Return $ this-> Error_OCCUR (0x0002, $ SRC);
IF ($ DST [Strlen ($ DST) -1]! = Directory_seParetor) $ DST. = Directory_seParator;
IF (true === $ SUB && $ SRC == $ this-> EXIST_DIR) Return true; / / The source path is the target path of the record
IF (True! == $ SUB) $ this-> exist_dir = ""; // Record the directory path IF existing in the target directory path before the directory (! $ this-> make_dir ($ dst)) Return False; // Create a directory
IF (false === $ i = $ this-> list_dir ($ src)) Return False; // Read Directory Error
For ($ j = 0, $ k = count ($ i); $ j <$ k; $ j ) ife (! $ 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_occur (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); // Copy file failed to delete new files
Return $ this-> Error_occur (0x0007, $ dst);
}
Return True;
}
}
/ **
* @] Method name [= move ()
* @] Purpose [=
* Move any folder, files, relative or absolute paths, will be paid after the file is completed, check if the error data is wrong
* @] Parameter [=
* String $ src_path Specifies the source path, file or directory you want to move.
* String $ DST_PATH Specifies the target content path, file or directory you want to move, and the nature is determined by $ src_path, which can be the next directory of $ src_path
* @] Return [= Boolean error Returns false, otherwise TRUE
* @] Author [= snakevil <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)) {// Processing Directory
IF (! is_readable ($ src)) Return $ this-> Error_OCCUR (0x0002, $ SRC);
IF ($ DST [Strlen ($ DST) -1]! = Directory_seParetor) $ 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); // Remove the upper part of the non-target directory
Return True;
} Else {
IF (! is_readable ($ src)) Return $ this-> Error_occur (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);
Return $ this-> Error_occur (0x0007, $ dst);
}
IF (! @unlink) Return $ this-> error_occur (0x0006, $ src); // Delete source file
Return True;
}
}
/ **
* @] Method Name [= no_comment ()
* @] Purpose [=
* Clear the annotation of C specification in the file
* @] Parameter [=
* String $ PATH Specifies the file to do
* @] Return [= Boolean error Returns false, otherwise TRUE
* @] Author [= snakevil <51js, bu, phpx> (snakevil@qq.com)
* @] See [=
* /
Function No_comment ($ PATH = ") {
IF (! is_file) Return $ this-> Error_occur (0x000b, __function__);
IF (! is_readable) Return $ this-> Error_occur (0x0006, $ PATH);
IF (! is_writeable) Return $ this-> Error_occur (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 file
Fclose ($ fm);
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) {// Handling Original Data
$ fstats = feof ($ fm);
For ($ I = 0; $ I <$ FBLEN; $ I ) {// Analysis File Content
If (! $ fstats && $ i 5> $ fblen) Break; / / The file is not fully read when the next buffer reading completes the next file content
$ J = Substr ($ FBUFFER, $ I, 2);
$ K = $ J [0];
IF ($ j == "/ *" &&! $ in_dq &&! $ in_sq &&! $ in_lc) {// Not in string and row bet release, block comments start
$ IN_BC = true;
$ i ;
} Elseif ($ j == "* /" && $ in_bc) {// block annotation end
$ IN_BC = false;
$ I = 2;
} Elseif ($ j == "//" &&! $ In_dq &&! $ In_sq &&! $ In_bc) {// line note begins
$ in_lc = true;
$ i ;
} Elseif ($ k == "/ r" || $ k == "/ n")) $ in_lc = false; // row comment end
Elseif ($ j == "|| $ j ==" /// "|| $ j ==" // ') {// escape character
$ TBuffer. = $ j;
$ i ;
CONTINUE;
Elseif ($ k == "" &&! $ In_sq &&! $ In_bc&&! $ In_lc) $ in_dq =! $ In_dq; // Double quotes string start, end
Elseif ($ K == "&&! $ IN_DQ &&! $ IN_BC &&! $ IN_LC) $ in_sq =! $ in_sq; // single quotes string start, end
IF ($ IN_LC || $ IN_BC) Continue; // In the comment, skip
$ TBuffer. = $ fbuffer [$ I];
}
$ FBUFFER = Substr ($ FBUFEER, $ I); // Abandoned the part
UNSET ($ I, $ J, $ K);
IF (! $ fstats) $ fbuffer. = FREAD ($ FH, $ this-> buffer_size);
IF ($ fstats || Strlen ($ TBuffer)> = $ this-> buffer_size) {// write legal data to temporary file
IF (! fwrite ($ TH, $ TBuffer)) {// Write failed, lack of space
Fclose ($ TH);
FLOCK ($ fh, lock_un);
Fclose ($ fm);
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 ($ fm); // Remift file pointer to the file
Rewind ($ TH);
$ I = $ j = "";
$ K = 0;
While (! FeOf ($ th)) {// writing temporary file data back source file
$ I = fgets ($ TH, $ THIS-> Buffer_size);
IF ($ j == ") {// get a newline system for a file system
$ J = Substr ($ I, -2);
IF ($ j == "/ r / n") $ k = 2;
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) fwrite ($ fH, $ i. $ j); // Clear the right space
Else Continue;
Else FWRITE ($ FH, RTRIM ($ I, "/ T"));
}
Fflush ($ fh); // Save, close the file
Ftruncate ($ FH, FTELL ($ FH));
Fclose ($ TH);
FLOCK ($ fh, lock_un);
Fclose ($ fm);
UNSET ($ I, $ J, $ K, $ FH, $ TH);
Return True;
}
}
/ **
* @] Error list [=
* 0x0001 Specify the directory does not exist
* 0x0002 Specify directory no reading rights
* 0x0003 Specify directory no write authority
* 0x0004 Specify directory no delete permission
* 0x0005 Specify the file does not exist
* 0x0006 Specify the file without reading rights
* 0x0007 Specify file no write authority
* 0x0008 Specify file no delete permission
* 0x0009 Specify file unable to lock
* 0x000A Specify the object does not exist
* 0x000B method specified parameter is incorrect
* 0x000c Unable to create temporary files
* 0x000D disk space is insufficient
* 0x000E
* 0x000f
* 0x0010
* 0x0011
*
* /
?>