PHP统计目录下的文件总数及代码行数

  1. <?php
  2. /**
  3. * @author xiaoxiao <x_824@sina.com> 2011-1-12
  4. * @link http://xiaoyaoxia.cnblogs.com/
  5. * @license
  6. * 统计目录下的文件行数及总文件数··去除注释
  7. */
  8. $obj = new caculatefiles();
  9. //如果设置为false,这不会显示每个文件的信息,否则显示
  10. $obj->setshowflag(false);
  11. //会跳过所有all开头的文件
  12. $obj->setfileskip(array('all'));
  13. $obj->run("d:phpappphp_tests");
  14. //所有文件,(默认格式为.php)
  15. $obj->setfileskip(array());
  16. $obj->run("d:phpappphp");
  17. $obj->setshowflag(true);
  18. //跳过所有i和a开头的文件,(比如接口和抽象类开头)
  19. $obj->setfileskip(array('i', 'a'));
  20. $obj->run("d:phpappphp");
  21. /**
  22. * 执行目录中文件的统计(包括文件数及总行数
  23. *
  24. * 1、跳过文件的时候:
  25. * 匹配的规则只是从文件名上着手,匹配的规则也仅限在开头。
  26. * 2、跳过文件中的注释行:
  27. * 匹配的规则只是从注释段落的头部匹配,如果出现// 及 *及 #及/*开头的行及空行会被跳过。所以类似/*这种多汗注释,每行的开头都必须加上*号,否则无法匹配到这种的注释。
  28. * 3、目录过滤:
  29. * 匹配的规则是从目录名的全名匹配
  30. */
  31. class caculatefiles {
  32. /**
  33. * 统计的后缀
  34. */
  35. private $ext = ".php";
  36. /**
  37. * 是否显示每个文件的统计数,开源代码phpfensi.com
  38. */
  39. private $showeveryfile = true;
  40. /**
  41. * 文件的的跳过规则
  42. */
  43. private $fileskip = array();
  44. /**
  45. * 统计的跳过行规则
  46. */
  47. private $lineskip = array("*", "/*", "//", "#");
  48. /**
  49. * 统计跳过的目录规则
  50. */
  51. private $dirskip = array(".", "..", '.svn');
  52. public function __construct($ext = '', $dir = '', $showeveryfile = true, $dirskip = array(), $lineskip = array(), $fileskip = array()) {
  53. $this->setext($ext);
  54. $this->setdirskip($dirskip);
  55. $this->setfileskip($fileskip);
  56. $this->setlineskip($lineskip);
  57. $this->setshowflag($showeveryfile);
  58. $this->run($dir);
  59. }
  60. public function setext($ext) {
  61. trim($ext) && $this->ext = strtolower(trim($ext));
  62. }
  63. public function setshowflag($flag = true) {
  64. $this->showeveryfile = $flag;
  65. }
  66. public function setdirskip($dirskip) {
  67. $dirskip && is_array($dirskip) && $this->dirskip = $dirskip;
  68. }
  69. public function setfileskip($fileskip) {
  70. $this->fileskip = $fileskip;
  71. }
  72. public function setlineskip($lineskip) {
  73. $lineskip && is_array($lineskip) && $this->lineskip = array_merge($this->lineskip, $lineskip);
  74. }
  75. /**
  76. * 执行统计
  77. * @param string $dir 统计的目录
  78. */
  79. public function run($dir = '') {
  80. if ($dir == '') return;
  81. if (!is_dir($dir)) exit('path error!');
  82. $this->dump($dir, $this->readdir($dir));
  83. }
  84. /**
  85. * 显示统计结果
  86. * @param string $dir 目录
  87. * @param array $result 统计结果(包含总行数,有效函数,总文件数
  88. */
  89. private function dump($dir, $result) {
  90. $totalline = $result['totalline'];
  91. $linenum = $result['linenum'];
  92. $filenum = $result['filenum'];
  93. echo "*************************************************************rn<br/>";
  94. echo $dir . ":rn<br/>";
  95. echo "totalline: " . $totalline . "rn<br/>";
  96. echo "totalline with no comment and empty: " . $linenum . "rn<br/>";
  97. echo 'totalfiles:' . $filenum . "rn<br/>";
  98. }
  99. /**
  100. * 读取目录
  101. * @param string $dir 目录
  102. */
  103. private function readdir($dir) {
  104. $num = array('totalline' => 0, 'linenum' => 0, 'filenum' => 0);
  105. if ($dh = opendir($dir)) {
  106. while (($file = readdir($dh)) !== false) {
  107. if ($this->skipdir($file)) continue;
  108. if (is_dir($dir . '/' . $file)) {
  109. $result = $this->readdir($dir . '/' . $file);
  110. $num['totalline'] += $result['totalline'];
  111. $num['linenum'] += $result['linenum'];
  112. $num['filenum'] += $result['filenum'];
  113. } else {
  114. if ($this->skipfile($file)) continue;
  115. list($num1, $num2) = $this->readfiles($dir . '/' . $file);
  116. $num['totalline'] += $num1;
  117. $num['linenum'] += $num2;
  118. $num['filenum']++;
  119. }
  120. }
  121. closedir($dh);
  122. } else {
  123. echo 'open dir <' . $dir . '> error!' . "r";
  124. }
  125. return $num;
  126. }
  127. /**
  128. * 读取文件
  129. * @param string $file 文件
  130. */
  131. private function readfiles($file) {
  132. $str = file($file);
  133. $linenum = 0;
  134. foreach ($str as $value) {
  135. if ($this->skipline(trim($value))) continue;
  136. $linenum++;
  137. }
  138. $totalnum = count(file($file));
  139. if (!$this->showeveryfile) return array($totalnum, $linenum);
  140. echo $file . "rn";
  141. echo 'totalline in the file:' . $totalnum . "rn";
  142. echo 'totalline with no comment and empty in the file:' . $linenum . "rn";
  143. return array($totalnum, $linenum);
  144. }
  145. /**
  146. * 执行跳过的目录规则
  147. * @param string $dir 目录名
  148. */
  149. private function skipdir($dir) {
  150. if (in_array($dir, $this->dirskip)) return true;
  151. return false;
  152. }
  153. /**
  154. * 执行跳过的文件规则
  155. * @param string $file 文件名
  156. */
  157. private function skipfile($file) {
  158. if (strtolower(strrchr($file, '.')) != $this->ext) return true;
  159. if (!$this->fileskip) return false;
  160. foreach ($this->fileskip as $skip) {
  161. if (strpos($file, $skip) === 0) return true;
  162. }
  163. return false;
  164. }
  165. /**
  166. * 执行文件中行的跳过规则
  167. * @param string $string 行内容
  168. */
  169. private function skipline($string) {
  170. if ($string == '') return true;
  171. foreach ($this->lineskip as $tag) {
  172. if (strpos($string, $tag) === 0) return true;
  173. }
  174. return false;
  175. }
  176. }
  177. ?>