php之文件操作

2016/06/26

PHP SPL中提供了SplFileInfo和SplFileObject两个类来处理文件操作

SplFileInfo用来获取文件详细信息

$file = new SplFileInfo('foo-bar.txt');
print_r(array(
    'getATime' => $file->getATime(), //最后访问时间
    'getBasename' => $file->getBasename(), //获取无路径的basename
    'getCTime' => $file->getCTime(), //获取inode修改时间
    'getExtension' => $file->getExtension(), //文件扩展名
    'getFilename' => $file->getFilename(), //获取文件名
    'getGroup' => $file->getGroup(), //获取文件组
    'getInode' => $file->getInode(), //获取文件inode
    'getLinkTarget' => $file->getLinkTarget(), //获取文件链接目标文件
    'getMTime' => $file->getMTime(), //获取最后修改时间
    'getOwner' => $file->getOwner(), //文件拥有者
    'getPath' => $file->getPath(), //不带文件名的文件路径
    'getPathInfo' => $file->getPathInfo(), //上级路径的SplFileInfo对象
    'getPathname' => $file->getPathname(), //全路径
    'getPerms' => $file->getPerms(), //文件权限
    'getRealPath' => $file->getRealPath(), //文件绝对路径
    'getSize' => $file->getSize(),//文件大小,单位字节
    'getType' => $file->getType(),//文件类型 file  dir  link
    'isDir' => $file->isDir(), //是否是目录
    'isFile' => $file->isFile(), //是否是文件
    'isLink' => $file->isLink(), //是否是快捷链接
    'isExecutable' => $file->isExecutable(), //是否可执行
    'isReadable' => $file->isReadable(), //是否可读
    'isWritable' => $file->isWritable(), //是否可写
));

SplFileObject继承SplFileInfo并实现RecursiveIterator , SeekableIterator接口 ,用于对文件遍历、查找、操作

  • 遍历:
try {
    foreach(new SplFileObject('foo-bar.txt') as $line) {
        echo $line;
    }
} catch (Exception $e) {
    echo $e->getMessage();
}
  • 查找指定行:
try {
    $file = new SplFileObject('foo-bar.txt');
    $file->seek(2);
    echo $file->current();
} catch (Exception $e) {
    echo $e->getMessage();
}
  • 写入csv文件:
$list  = array (
    array( 'aaa' ,  'bbb' ,  'ccc' ,  'dddd' ),
    array( '123' ,  '456' ,  '7891' ),
    array( '"aaa"' ,  '"bbb"' )
);
$file  = new  SplFileObject ( 'file.csv' ,  'w' );
foreach ( $list  as  $fields ) {
    $file -> fputcsv ( $fields );
}
自己根据这些封装了一个文件操作的php类,可用于文件内容的读、写、文件的拷贝和移动、删除等……

[fileSys.php]

<?php
/**
 * 文件系统操作类
 * 
 */
class FileSystem {
    /**
     * 单例对象
     * 
     * @var FileSystem
     */
    private static $instance;
    private function __construct() {}
    /**
     * 获取单例
     * 
     * @return FileSystem
     */
    public static function getInstance() {
        if (null === self::$instance) {
            self::$instance = new self();
        }
        return self::$instance;
    }
    /**
     * 读取文件内容
     * 
     * @param File $file 要读取的文件
     * @return string 
     */
    public function read(File $file) {
        if (!$file->exists()) {
            throw new \Exception("The specified file '{$file}' doesn't exist.");
        }
        return $file->content();
    }

    /**
     * 将内容数据写入文件
     * 
     * @param File $file 要被写入数据的文件
     * @param string $content 要写入的数据
     * @param boolean $append 是否为追加数据而不是覆盖,默认为覆盖
     * @return int
     */
    public function write(File $file, $content, $append = false) {
        if (!$file->exists()) {
            $dir = new Dir($file->getPath());
            if (!$dir->exists() && !$dir->create()) {
                return false;
            }
        }
        return $file->write($content, $append);
    }

    /**
     * 删除一个文件
     * 
     * @param File $file 待删除的文件
     * @return boolean
     */
    public function remove(File $file) {
        if ($file->exists()) {
            return $file->remove();
        }
        return true;        
    }

    /**
     * 复制文件
     * 
     * @param File $src 源文件
     * @param File $dest 目标文件
     * @return boolean
     */
    public function copy(File $src, File $dest) {
        if(!$src->exists()) {
            return false;
        }
        $dir = new Dir($dest->getPath());
        if (!$dir->exists() && !$dir->create()) {
            return false;
        }
        return $src->copyTo($dest);
    }

    /**
     * 移动(重命名)文件
     * 
     * @param File $src 源文件
     * @param File $dest 目标文件
     * @return boolean
     */
    function move(File $src, File $dest) {
        if(!$src->exists()) {
            return false;
        }
        $dir = new Dir($dest->getPath());
        if (!$dir->exists() && !$dir->create()) {
            return false;
        }
        return $src->rename($dest);
    }

    /**
     * 复制目录(把源目录下的所有子目录及文件复制到目标目录下)
     * 
     * @param Dir $src 源目录
     * @param Dir $dest 目标目录,不存在时将会被创建
     * @return boolean
     */
    public function copyDir(Dir $src, Dir $dest) {
        if(!$src->exists()) {
            return false;
        }
        if (!$dest->exists() && !$dest->create()) {
            return false;
        }
        $files = $src->listing();
        foreach ($files as $f) {
            $_dest = $dest . '/' . $f->getFilename();
            if ($f->isFile()) {
                $f->copyTo($_dest);
            } else if($f->isDir()) {
                $this->copy($f, new Dir($_dest));
            }
        }
        return true;
    }

    /**
     * 移动目录(把源目录下的所有子目录及文件移动到目标目录下,源目录将会被删除)
     * 
     * @param Dir $src 源目录
     * @param Dir $dest 目标目录,不存在时将会被创建
     * @return boolean
     */
    function moveDir(Dir $src, Dir $dest) {
        if(!$src->exists()) {
            return false;
        }
        if (!$dest->exists() && !$dest->create()) {
            return false;
        }
        $files = $src->listing();
        foreach ($files as $f) {
            $_dest = $dest . '/' . $f->getFilename();
            if ($f->isFile()) {
                $f->rename($_dest);
            } else if($f->isDir()) {
                $this->moveDir($f, new Dir($_dest));
                rmdir($f);
            }
        }
        return rmdir($src);
    }

    /**
     * 在目录下查找指定扩展名的文件列表(不包含子目录)
     * 
     * @param Dir $dir 查找目录
     * @param string $ext 文件扩展名,如txt
     * @return array
     */
    public function findByExt(Dir $dir, $ext) {
        $arr =[];
        $files = $dir->listing();
        foreach ($files as $f) {
            if (!$f->isFile()) {
                continue;
            }
            $info = pathinfo($f);
            if (isset($info['extension']) && $info['extension'] == $ext) {
                $arr[] = $f;
            }
        }
        return $arr;
    }
}

/**
 * 文件类
 */
class File extends \SplFileInfo implements FileOperable {
    /**
     * 文件的路径(包括文件名)
     * 
     * @var string
     */
    protected $pathname;
        
    /**
     * 构造方法,设置当前文件
     * 
     * @param string $pathname 文件的路径
     */
    public function __construct($pathname) {
        parent::__construct($pathname);
        
        $this->pathname = $pathname;
    }
    
    /**
     * 析构方法
     */
    public function __destruct() {
        unset($this->pathname);
    }
    
    /**
     * 创建文件
     * 
     * @return boolean
     */
    public function create() {
        return touch($this->pathname) && chmod($this->pathname, 0666);
    }
    
    /**
     * 删除文件
     *
     * @return boolean
     */
    public function remove() {
        return unlink($this->pathname);
    }
    
    /**
     * 文件重命名
     * 
     * @param string $newname 新的文件名
     * @return boolean
     */
    public function rename($newname) {
        if (rename($this->pathname, $newname)) {
            $this->pathname = $newname;
            return true;
        }
        return false;
    }
    
    /**
     * 判断文件是否存在
     * 
     * @return boolean
     */
    public function exists() {
        return $this->isFile();
    }
    
    /**
     * 将$source文件拷贝覆盖当前文件
     * 
     * @param string $source 源文件路径
     * @return boolean
     */
    public function copyFrom($source) {
        return copy($source, $this->pathname);
    }
    
    /**
     * 将当前文件拷贝到$dest
     * 
     * @param string $dest 目标文件路径
     * @return boolean
     */
    public function copyTo($dest) {
        return copy($this->pathname, $dest);
    }
    
    /**
     * 将内容写入文件
     * 
     * @param string $content 要写入的数据
     * @param boolean $append 是否为追加数据而不是覆盖,默认为覆盖
     * @return int
     */
    public function write($content, $append = false) {
        $flags = $append ? FILE_APPEND | LOCK_EX : null;
        return file_put_contents($this->pathname, $content, $flags);
    }
    
    /**
     * 读取整个文件内容
     *
     * @param File $file 要读取的文件
     * @return string
     */
    public function content() {
        return file_get_contents($this->pathname);
    }
    
    /**
     * 获取文件大小的字节数
     * 
     * @return int
     */
    public function size() {
        return $this->getSize();
    }
    
    /**
     * 获取文件的扩展名
     * 
     * @return string
     */
    public function ext() {
        return $this->getExtension();
    }
    
    /**
     * 获取文件名
     * 
     * @return string
     */
    public function name() {
        return $this->getBasename();
    }
    
    /**
     * 获取文件流操作对象
     * 
     * @param string $mode 文件流的访问类型
     * @return FileStream
     */
    public function stream($mode = 'r') {
        return new FileStream($this->pathname, $mode);
    }
    
}

/**
 * 目录类
 * 
 */
class Dir extends \SplFileInfo implements FileOperable {
    /**
     * 目录的路径
     * 
     * @var string
     */
    protected $path;

    /**
     * 构造方法,设置当前目录
     * 
     * @param string $path 目录的路径
     */
    public function __construct($path) {
        parent::__construct($path);
        
        $this->path = rtrim($path, '/');
    }

    /**
     * 析构方法
     */
    public function __destruct() {
        unset($this->path);
    }
    
    /**
     * 创建目录
     * 
     * @return boolean
     */
    public function create() {
        if (!$this->exists()) {
            $arr = explode('/', str_replace("\\", "/", $this->path));
            $build = '';
            foreach($arr as $dir) {
                if(strstr($dir, ":") != false) {
                    $build = $dir;
                    continue;
                }
                $build .= "/$dir";
                if (!is_dir($build)) {
                    if (!mkdir($build, 0777)) {
                        return false;
                    }
                    chmod($build, 0777);
                }
            }
        }
        return true;
    }
    
    /**
     * 删除目录
     * 
     * @return boolean
     */
    public function remove() {
        $this->clear();
        return rmdir($this->path);
    }
    
    /**
     * 删除目录下所有文件,但不删除当前目录
     * 
     * @return void
     */
    public function clear() {
        $list = $this->listing();
        foreach($list as $f) {
            $f->remove();
        }
    }
    
    /**
     * 重命名目录
     * 
     * @param string $name 新目录名称(包含完整路径)
     * @return boolean
     */
    public function rename($newname) {
        if (rename($this->path, $newname)) {
            $this->path = $newname;
            return true;
        }
        return false;
    }

    /**
     * 判断目录是否存在
     *
     * @return boolean
     */
    public function exists() {
        return $this->isDir();
    }
    
    /**
     * 判断目录是否为空
     * 
     * @return boolean
     */
    public function isEmpty() {
        return $this->listing() ? false : true;
    }
    
    /**
     * 获取目录下所有子目录及文件
     * 
     * @return array
     */
    public function listing() {
        $arr = [];
        $i = new \DirectoryIterator($this->path);
        foreach($i as $f) {
            if(!$f->isDot()) {
                $path = $f->getRealPath();
                $arr[] = $f->isDir() ? new Dir($path) : new File($path);
            }
        }
        return $arr;
    }
}

/**
 * 文件流操作封装类
 * 
 */
class FileStream {
    /**
     * 文件流操作指针资源
     * 
     * @var resource
     */
    protected $handle;

    /**
     * 构造方法,生成文件流操作指针资源
     *
     * @param string $name 文件的路径
     * @param string $mode 文件流访问类型
     */
    public function __construct($name, $mode = 'r', $handle = null) {
        if (is_resource($handle)) {
            $this->handle = $handle;
        }
        else {
            $this->handle = fopen($name, $mode);
        }
    }

    /**
     * 析构方法,关闭已打开的文件指针
     */
    public function __destruct() {
        $this->close();
    }

    /**
     * 关闭已打开的文件指针
     * 
     * @return void
     */
    public function close() {
        if (is_resource($this->handle)) {
            fclose($this->handle);
        }
        unset($this->handle);
    }

    /**
     * 获取当前已打开的文件指针
     *
     * @return resource
     */
    public function getHandle() {
        return $this->handle;
    }

    /**
     * 读取最多length个字节
     *
     * @param int $length 最多读取length个字节
     * @return string
     */
    public function read($length) {
        return fread($this->handle, $length);
    }
    
    /**
     * 读取文件所有字节
     *
     * @param int $bucketSize 一次读取的字节数
     * @return string
     */
    public function readAll($bucketSize = 4096) {
        $contents = "";
        while (!$this->eof()) {
            $contents .= $this->read($bucketSize);
        }
        return $contents;
    }

    /**
     * 从文件指针中读取一行
     *
     * @param int $length 读取一行最多length - 1个字节,省略为读取数据直到行结束
     * @return string
     */
    public function getLine($length = 0) {
        $content = null;

        if (0 < $length) {
            $content = fgets($this->handle, $length);
        }
        else {
            $content = fgets($this->handle);
        }

        return $content;
    }

    /**
     * 写入lendth个字节到文件指针处
     * 
     * @param string $content 要写入的字符串内容
     * @param int $length 若指定了length,写入length个字节后将停止写入
     * @return int
     */
    public function write($content, $length = null) {
        $writtenBytes = 0;
        
        if (is_null($length)) {
            $writtenBytes = fwrite($this->handle, $content);
        }
        else {
            $writtenBytes = fwrite($this->handle, $content, $length);
        }

        return $writtenBytes;
    }

    /**
     * 测试文件指针是否到了文件结束的位置
     * 
     * @return boolean
     */
    public function eof() {
        return feof($this->handle);
    }

    /**
     * 倒回文件指针的位置
     * 
     * @return boolean
     */
    public function rewind() {
        rewind($this->handle);
    }
}

/**
 * 文件或目录操作接口
 * 
 */
interface FileOperable {
	/**
	 * 创建文件或目录
	 */
	public function create();
	
	/**
	 * 删除文件或目录
	 */
	public function remove();
	
	/**
	 * 重命名文件或目录
	 * 
	 * @param string $newname 新的文件或目录名
	 */
	public function rename($newname);
	
	/**
	 * 检查文件或目录是否存在
	 */
	public function exists();
	
}
?>

[demo]

<?php

include_once __DIR__.'/fileSys.php';

$fileSys = FileSystem::getInstance();

//在某个目录下查找指定扩展名的列表
$path = __DIR__;
$res1 = $fileSys->findByExt(new Dir($path), 'txt');
$res2 = $fileSys->findByExt(new Dir($path), 'php');
if(!empty($res1)) {
	foreach($res1 as $file) {
		echo $file->name().PHP_EOL;
	}
}
echo PHP_EOL;

$file = null;
if(!empty($res2)) {
	foreach($res2 as $file) {
		echo $file->name().PHP_EOL;
	}
}
exit;

//移动目录
$src = __DIR__.'/files_copy';
$dest = __DIR__.'/files_move';
$res = $fileSys->moveDir(new Dir($src), new Dir($dest));
var_dump($res);
exit;

//复制目录
$src = __DIR__.'/files';
$dest = __DIR__.'/files_copy';
$res = $fileSys->copyDir(new Dir($src), new Dir($dest));
var_dump($res);
exit;

//移动/重命名文件
$src = __DIR__.'/readtest.txt';
$dest = __DIR__.'/read.txt';
$res = $fileSys->move(new File($src), new File($dest));
var_dump($res);
exit;

//复制文件
$src = __DIR__.'/readtest.txt';
$dest = __DIR__.'/copy/read.txt';
$res = $fileSys->copy(new File($src), new File($dest));
var_dump($res);
exit;

//删除一个文件
$file = __DIR__.'/files/test.txt';
$res = $fileSys->remove(new File($file), 'tonytest');
var_dump($res);
exit;

//写文件
$file = __DIR__.'/files/writetest.txt';
$res = $fileSys->write(new File($file), 'tonytest');
var_dump($res);
exit;


//读取文件内容
$file = __DIR__.'/readtest.txt';
$content = $fileSys->read(new File($file));
echo $content;

Post Directory