统计项目的代码行数

605 阅读2分钟

一、思路

1. 找出代码文件

项目中的文件琳琅满目,我们需要在所有文件中找出代码文件,则需要过滤掉不符合条件的文件夹或文件。读取时,需要对项目文件夹进行递归,找出所有符合条件的代码文件,等待使用。

2. 逐行读取每个代码文件,统计行数

要想统计代码行数,则必然要读取代码文件的文本内容,我们选择逐行读取的方式(其实对应了比较大的缓冲区而已),如果读取到的行不是空行,则记录一个有效行数(还可以将规则设置的更严格,例如一行至少需要5个文字才计算在内)。最后,将读取到的所有代码文件的行数汇总,即为项目中的代码文件行数。

二、实现

以下封装了两个基础函数,一个用于递归读取项目下的文件,并可以设置过滤规则。另一个则是逐行读取文件内容,统计文件行数。

var fs = require('fs')
var { join } = require('path')
var readline = require('readline')

/**
 * 读取项目中的所有文件(除符合过滤条件的文件外)
 * @param {String} path 项目路径
 * @param  {...any} filters 过滤条件,符合的条件将会过滤,可过滤目录或文件
 */
function readFiles(path, ...filters) {

  var allFiles = []
  doRead(path)

  function doRead(path) {
    var files = fs.readdirSync(path, {
      withFileTypes: true
    })
    files.forEach(file => {
      var pass = filters.some(filter => filter(file))
      if (!pass) {
        if (file.isDirectory()) {
          doRead(join(path, file.name))
        } else {
          allFiles.push({
            path: join(path, file.name)
          })
        }
      }
    })
  }

  return allFiles
}

/**
 * 统计文件行数
 * @param {String} path 文件路径,如d:/1.txt
 * @param {Function} callback 回调
 */
function statLines(path, callback) {
  let total = 0
  const rl = readline.createInterface({
    input: fs.createReadStream(path)
  })
  rl.on('line', line => {
    total++
  })
  rl.once('close', () => {
    callback(null, total)
  })
}

module.exports = {
  readFiles,
  statLines
}

接下来,通过对上述两个通用函数的调用,统计总行数。


var { readFiles, statLines } = require('./file')

var files = readFiles('/project', file => {
  return file.isDirectory() && (file.name === 'node_modules' || file.name === 'public')
}, file => {
  return file.isFile() && !/(vue|js)$/.test(file.name)
})

var total = 0
var run = 0, need = files.length
files.forEach(file => {
  statLines(file.path, (err, count) => {
    total += count
    if (++run >= need) {
      console.log(total)
    }
  })
})