1. 程式人生 > >PHP-檔案和目錄操作

PHP-檔案和目錄操作

目錄操作

  • 建立目錄:mkdir(目錄地址, 許可權, 是否遞迴建立=false);
  • 刪除目錄:rmdir(目錄地址);(僅僅可以刪除空目錄,不支援遞迴刪除)
  • 移動(改名):rename(舊地址, 新地址);

注意:目錄地址用絕對路徑,./或../開頭(windows下直接/開頭不認,linux沒測試)

獲取目錄內容

<?php
$path = './';
//開啟資料夾
$dir_handle = opendir($path);
//讀取資料夾
while(false !== $file = readdir($dir_handle)){
  if ($file == '.' || $file == '..') continue;
  echo $file, '<br>';
}
//關閉資料夾
closedir($dir_handle);

遞迴獲取目錄內容

<?php
$path = './';

function read_dirs_tree($path, $deep=0){
  //開啟資料夾
  $dir_handle = opendir($path);
  //讀取資料夾
  while(false !== $file = readdir($dir_handle)){
    if ($file == '.' || $file == '..') continue;
    echo str_repeat('-', $deep*4), $file, '<br>';
    //是否是目錄
    if (is_dir($path.'/'.$file)) {
      //是目錄,呼叫自身
      $func_name = __FUNCTION__;
      $func_name($path.'/'.$file, $deep+1);
    }
  }
  //關閉資料夾
  closedir($dir_handle);
}

read_dirs_tree($path);

目錄檔名編碼問題

Windows預設使用gbk編碼

  1. 專案->windows:iconv('UTF-8', 'GBK', 字串);
  2. windows->專案:iconv('GBK', 'UTF-8', 字串);

檔案上傳

瀏覽器端

form設定:method="post" enctype="multipart/form-data"

伺服器端

PHP伺服器在接受到檔案型的表單資料後將檔案儲存於上傳臨時目錄(在腳本週期內有效)
php.ini配置:

  1. upload_tmp_dir:修改上傳的臨時檔案的路徑
  2. max_file_uploads:修改最多上傳檔案數
  3. post_max_size:修改最大post資料最大限制
  4. php_fileinfo.dll:開啟MIME檢測拓展

error分類(0:上傳成功):

  • 1:檔案過大,大於php的配置
  • 2:檔案過大,超過了表單元素max_file_size(目前也是伺服器PHP判斷的。但是PHP提出希望當檔案過大時,在瀏覽器請求時就可以利用該值進行判斷大小)
  • 3:上傳部分檔案。
  • 4:沒有上傳檔案。
  • 5:邏輯上,上傳的為空檔案(長度為0)
  • 6:沒有找到臨時上傳目錄(許可權控制)。
  • 7:臨時檔案寫入失敗(磁碟空間,許可權)。

<form action="" method="post" enctype="multipart/form-data">
  <input type="file" name="upload_file">
  <input type="submit" value="上傳">
</form>

<?php
class Upload{
  private $_max_size;
  private $_type_map;
  private $_allow_ext_list;
  private $_allow_mime_list;
  private $_upload_path;
  private $_prefix;
  //儲存檔案上傳的錯誤資訊
  private $_error;
  public function getError() {
    return $this->_error;
  }

  public function __construct() {
    $this->_max_size = 1024*1024;
    //設定一個字尾名與mime的對映關係,就可以只修改允許的字尾名,就可以影響到$allow_ext_list和$allow_mime_list
    $this->_type_map = array(
      '.png'  => array('image/png', 'image/x-png'),
      '.jpg'  => array('image/jpeg', 'image/pjpeg'),
      '.jpeg' => array('image/jpeg', 'image/pjpeg'),
      '.gif'  => array('image/gif'),
      );
    $this->_allow_ext_list = array('.png', '.jpg');
    $allow_mime_list = array();
    foreach($this->_allow_ext_list as $value) {
      //得到每個字尾名(將所有$this->_type_map下的陣列元素合併成新陣列)
      $allow_mime_list = array_merge($allow_mime_list, $this->_type_map[$value]);
    }
    // 去重
    $this->_allow_mime_list = array_unique($allow_mime_list);
    // 合併,去重後$allow_mime_list = array('image/png', 'image/gif', 'image/jpeg', 'image/pjpeg', 'image/x-png');
    $this->_upload_path = './';
    $this->_prefix = '';
  }

  public function __set($p, $v) {//屬性過載
    $allow_set_list = array('_upload_path', '_prefix', '_allow_ext_list', '_max_size');
    //給沒有加上"_"的引數新增"_"
    if(substr($p, 0, 1) !== '_') {
      $p = '_' . $p;
    }

    $this->$p = $v;
  }


  /**
   * 上傳單個檔案
   */
  public function uploadOne($tmp_file) {

    # 是否存在錯誤
    if($tmp_file['error'] != 0) {
      $this->_error = '檔案上傳錯誤';
      return false;
    }

    # 尺寸
    if ($tmp_file['size'] > $this->_max_size) {
      $this->_error = '檔案過大';
      return false;
    }

    # 型別
    # 從原始檔名中提取字尾
    $ext = strtolower(strrchr($tmp_file['name'], '.'));
    if (!in_array($ext, $this->_allow_ext_list)) {
      $this->_error = '型別不合法';
      return false;
    }

    # MIME, type元素。
    if (!in_array($tmp_file['type'], $this->_allow_mime_list)) {
      $this->_error = '型別不合法';
      return false;
    }

    //PHP自己獲取檔案的mime,進行檢測
    $finfo = new Finfo(FILEINFO_MIME_TYPE);//獲得一個可以檢測檔案MIME型別資訊的物件
    $mime_type = $finfo->file($tmp_file['tmp_name']);//檢測
    if (!in_array($mime_type, $this->_allow_mime_list)) {
      $this->_error = '型別不合法';
      return false;
    }

    # 移動
    # 上傳檔案儲存地址
    //建立子目錄
    $subdir = date('YmdH') . '/';
    if(!is_dir($this->_upload_path . $subdir)) {//檢測是否存在
      //不存在
      mkdir($this->_upload_path . $subdir);
    }

    # 上傳檔案起名
    $upload_filename = uniqID($this->_prefix, true) . $ext;
    if (move_uploaded_file($tmp_file['tmp_name'], $this->_upload_path . $subdir . $upload_filename)) {
      // 移動成功,返回檔名
      return $subdir . $upload_filename;
    } else {
      // 移動失敗
      $this->_error = '移動失敗';
      return false;
    }

  }
}
var_dump($_FILES);
if ($_FILES) {
  $upload = new Upload();

  if ($new_filename = $upload->uploadOne($_FILES['upload_file'])) {
    echo $new_filename;
  }else{
    echo $upload->getError();
  }
}

檔案操作

寫入file_put_contents(檔案地址, 內容)

檔案不存在則自動建立
預設為替換寫,第三個引數使用FILE_APPEND常量表示追加寫

讀取file_get_contents(檔案地址)

當操作的檔案過大時不能一次性操作全部檔案內容這個函式不適用!

<?php
$file = './test.txt';
$content = date('H:i:s').'\n';
var_dump(file_put_contents($file, $content));//返回位元組數

file_put_contents($file, $content, FILE_APPEND);//追加寫

var_dump(file_get_contents($file));

使用檔案控制代碼和指標操作檔案

開啟檔案控制代碼:fopen(檔案地址, 開啟方式);

PHP提供瞭如下開啟模式(+擴充套件,擴充套件了操作):

  1. r(read)讀模式
  2. w(write)替換寫模式,將檔案內容清零,自動建立不存在的檔案,只能開啟已經存在的檔案
  3. a(append)追加寫模式
  4. x 替換寫,不會自動建立不存在的檔案
  5. r+讀寫模式,將檔案指標放在檔案開頭。
  6. w+讀替換寫模式,將檔案內容清零,將檔案指標放在檔案開頭,自動建立不存在的檔案。
  7. a+讀追加寫模式,寫操作永遠在檔案末尾,讀操作受限於檔案指標。
  8. x+讀替換寫模式,將檔案內容清零,將檔案指標放在檔案開頭,不會自動建立不存在的檔案,只能開啟已經存在的檔案

讀取指定長度的字串內容(單位位元組):fread(檔案控制代碼, 長度);

長度最大值為8192個位元組。

讀取指定長度的字串內容(單位位元組):fgets(檔案控制代碼, 長度);

長度:指的是會讀取長度-1個位元組
行末也是該函式的終止讀操作條件
終止讀取取決於先滿足那個條件,因此該函式也稱讀行函式
最常用:fgets($handle, 1024)

一次讀取一個位元組的資料:fgetc(檔案控制代碼);

讀取指標位置字元,操作時會移動指標。

在指定位置寫入內容:fwrite(檔案控制代碼,寫入內容);

位置通常由檔案指標來指示,如果是a模式,不論指標在哪裡,只能在末尾寫。

關閉檔案控制代碼:fclose();

其他檔案函式

  1. ftell(檔案控制代碼)獲取指標位置
  2. fseek(檔案控制代碼, int $offset)設定指標位置
  3. filemtime(檔案地址)檔案的最後修改時間
  4. filesize(檔案地址)檔案大小
<?php
$file = './test.txt';
header('Content-type:text/html;charset=utf-8');
$file_handle = fopen($file, 'w+');
fwrite($file_handle, "中文字元和位元組");

fseek($file_handle, 0);
echo'fread:',fread($file_handle, 5),'<hr/>';//中?
echo'fgets:',fgets($file_handle, 2),'<hr/>';//?
echo'fgetc:',fgetc($file_handle),'<hr/>';//?
echo'ftell:',ftell($file_handle),'<hr/>';//7
echo'filemtime:',filemtime($file),'<hr/>';//1487850244
echo'filesize:',filesize($file),'<hr/>';//21(3*7)
fclose($file_handle);