统计源代码行数的工具(含源码)

        今天突然想统计一下代码的行数,没有想太多就动手写了一个。写完才发现是重复造轮子,网上已经有这样的工具了。既然造了,那就共享出来,能用得上的,就用用。

        开发环境VS2012,.net 2.0

代码经过调整的,算是比较负责任。

 

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Text.RegularExpressions;
using System.Diagnostics;

namespace SourceCodeAnalysis
{
    public partial class FrmLinesOfCodeStatistics : Form
    {
        public FrmLinesOfCodeStatistics()
        {
            InitializeComponent();
        }

        private void btnDoStatistics_Click(object sender, EventArgs e)
        {
            if (!Directory.Exists(txtCodePath.Text))
            {
                MessageBox.Show("请选择源文件夹路径");
                return;
            }

            List<CodeFileCounter> codeFileCounterList =
                GetAllFilesStatistics(txtCodePath.Text, cbSeacheSubFolder.Checked, txtSourceFileExtension.Text, cbNoEmptyLine.Checked, txtOutOfStatistics.Text);

            FillToGrid(codeFileCounterList, txtCodePath.Text);
        }

        private void FillToGrid(List<CodeFileCounter> codeFileCounterList, string sourceFoloder)
        {
            dataGridView1.Rows.Clear();
            int totalEmptyLines = 0;
            int totalCustomExclusionLines = 0;
            int totalCodeLines = 0;
            int totalTotalLine = 0;
            foreach (var fileCounter in codeFileCounterList)
            {
                int rowid = dataGridView1.Rows.Add();
                DataGridViewRow row = dataGridView1.Rows[rowid];
                row.Cells[0].Value = fileCounter.FilePath.Replace(sourceFoloder, "");
                row.Cells[1].Value = fileCounter.BlankLine;
                row.Cells[2].Value = fileCounter.CustomExclusionLine;
                row.Cells[3].Value = fileCounter.CodeLine;
                row.Cells[4].Value = fileCounter.TotalLine;
                row.Tag = fileCounter;

                totalEmptyLines += fileCounter.BlankLine;
                totalCustomExclusionLines += fileCounter.CustomExclusionLine;
                totalCodeLines += fileCounter.CodeLine;
                totalTotalLine += fileCounter.TotalLine;
            }

            int totalRowId = dataGridView1.Rows.Add();
            DataGridViewRow totalRow = dataGridView1.Rows[totalRowId];
            totalRow.Cells[0].Value = "汇总:";
            totalRow.Cells[1].Value = totalEmptyLines;
            totalRow.Cells[2].Value = totalCustomExclusionLines;
            totalRow.Cells[3].Value = totalCodeLines;
            totalRow.Cells[4].Value = totalTotalLine;
        }

        /// <summary>
        /// 获取所有文件的统计信息
        /// </summary>
        /// <param name="sourceFloder">源代码文件目录</param>
        /// <param name="isSeachSubFolder">是否获取子文件夹的文件。true,获取所有子文件夹的文件</param>
        /// <param name="fileExtensions">要获取的文件的扩展名。多个扩展名用“|”分割,如:*.txt|*.cs 。 ""、"*","*.*"表示所有文件</param>
        /// <param name="notCountBlankLine">不统计空行</param>
        /// <param name="customExclusions">用户定义的排除行规则。一个规则一行。</param>
        /// <returns></returns>
        private List<CodeFileCounter> GetAllFilesStatistics(string sourceFloder, bool isSeachSubFolder, string fileExtensions, bool notCountBlankLine, string customExclusions)
        {
            List<CodeFileCounter> codeFileCounterList = new List<CodeFileCounter>();
            foreach (string fileName in GetDirectoryFiles(sourceFloder, fileExtensions, isSeachSubFolder))
            {
                codeFileCounterList.Add(new CodeFileCounter(fileName, notCountBlankLine, customExclusions));
            }
            return codeFileCounterList;
        }

        /// <summary>
        /// 获取源文件夹下的所有文件.
        /// </summary>
        /// <param name="sourceFoloder">源代码文件目录</param>
        /// <param name="extensions">要获取的文件的扩展名。多个扩展名用“|”分割,如:*.txt|*.cs 。 ""、"*","*.*"表示所有文件 </param>
        /// <param name="isSeachSubFolder">是否获取子文件夹的文件。true,获取所有子文件夹的文件</param>
        /// <returns></returns>
        private static List<string> GetDirectoryFiles(string sourceFoloder, string fileExtensions, bool isSeachSubFolder)
        {
            string[] extensions = ConvertExtensionsToArray(fileExtensions);
            List<string> fileList = new List<string>();
            foreach (string file in Directory.GetFiles(sourceFoloder))
            {
                if (extensions.Length == 0 || extensions[0] == "*")
                {
                    fileList.Add(file);
                    continue;
                }
                foreach (var ext in extensions)
                {
                    if (file.Substring(file.Length - ext.Length, ext.Length) == ext)
                    {
                        fileList.Add(file);
                        break;
                    }
                }
            }
            if (isSeachSubFolder)
            {
                foreach (string folder in Directory.GetDirectories(sourceFoloder))
                {
                    fileList.AddRange(GetDirectoryFiles(folder, fileExtensions, true));
                }
            }
            return fileList;
        }

        /// <summary>
        /// 将*.cs|*.cpp转化为["cs","cpp"]这种类型的数组.
        /// </summary>
        /// <param name="fileExtensions"></param>
        /// <returns></returns>
        private static string[] ConvertExtensionsToArray(string fileExtensions)
        {
            string[] extensions = fileExtensions.Split('|');
            for (int i = 0; i < extensions.Length; i++)
            {
                extensions[i] = extensions[i].Replace("*.", "");
            }
            return extensions;
        }

        private void btnBrowse_Click(object sender, EventArgs e)
        {
            if (openFileDialog1.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            {
                txtCodePath.Text = Path.GetDirectoryName(openFileDialog1.FileName);
            }
        }

        private void button1_Click(object sender, EventArgs e)
        {
            SaveToExcel(dataGridView1);
        }

        private static void SaveToExcel(DataGridView dgv)
        {
            SaveFileDialog kk = new SaveFileDialog();
            kk.Title = "保存EXECL文件";
            kk.Filter = "EXECL文件(*.xls)|*.xls|所有文件(*.*)|*.*";
            kk.FilterIndex = 1;
            if (kk.ShowDialog() == DialogResult.OK)
            {
                string FileName = kk.FileName;
                if (File.Exists(FileName))
                    File.Delete(FileName);
                FileStream objFileStream;
                StreamWriter objStreamWriter;
                string strLine = "";
                objFileStream = new FileStream(FileName, FileMode.OpenOrCreate, FileAccess.Write);
                objStreamWriter = new StreamWriter(objFileStream, System.Text.Encoding.Unicode);
                for (int i = 0; i < dgv.Columns.Count; i++)
                {
                    if (dgv.Columns[i].Visible == true)
                    {
                        strLine = strLine + dgv.Columns[i].HeaderText.ToString() + Convert.ToChar(9);
                    }
                }
                objStreamWriter.WriteLine(strLine);
                strLine = "";

                for (int i = 0; i < dgv.Rows.Count; i++)
                {
                    if (dgv.Columns[0].Visible == true)
                    {
                        if (dgv.Rows[i].Cells[0].Value == null)
                            strLine = strLine + " " + Convert.ToChar(9);
                        else
                            strLine = strLine + dgv.Rows[i].Cells[0].Value.ToString() + Convert.ToChar(9);
                    }
                    for (int j = 1; j < dgv.Columns.Count; j++)
                    {
                        if (dgv.Columns[j].Visible == true)
                        {
                            if (dgv.Rows[i].Cells[j].Value == null)
                                strLine = strLine + " " + Convert.ToChar(9);
                            else
                            {
                                string rowstr = "";
                                rowstr = dgv.Rows[i].Cells[j].Value.ToString();
                                if (rowstr.IndexOf("\r\n") > 0)
                                    rowstr = rowstr.Replace("\r\n", " ");
                                if (rowstr.IndexOf("\t") > 0)
                                    rowstr = rowstr.Replace("\t", " ");
                                strLine = strLine + rowstr + Convert.ToChar(9);
                            }
                        }
                    }
                    objStreamWriter.WriteLine(strLine);
                    strLine = "";
                }
                objStreamWriter.Close();
                objFileStream.Close();
                MessageBox.Show("保存EXCEL成功", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
            }
        }

        private void dataGridView1_CellDoubleClick(object sender, DataGridViewCellEventArgs e)
        {
            if (e.ColumnIndex == 0 && e.RowIndex >= 0)
            {
                CodeFileCounter cfc = (CodeFileCounter)dataGridView1.Rows[e.RowIndex].Tag;
                if (cfc != null)
                {
                    Process.Start("Notepad.exe", cfc.FilePath);
                }
            }
        }
    }

    class CodeFileCounter
    {
        private string filePath;
        private string customExclusionsPattern; //自定义排出行匹配模式
        private bool notCountBlankLine;
        private string[] lines;
        private int blankLine = 0;
        private int customExclusionLine = 0;

        private bool isCalculated = false;        //是否计算过

        /// <summary>
        /// 构造数组代码文件统计对象
        /// </summary>
        /// <param name="codeFilePath">代码文件路径</param>
        /// <param name="notCountBlankLine">不统计空白行</param>
        /// <param name="customExclusions">用户自定义排除项。每一行代表一个排除项</param>
        public CodeFileCounter(string codeFilePath, bool notCountBlankLine, string customExclusions)
        {
            this.filePath = codeFilePath;
            this.notCountBlankLine = notCountBlankLine;
            this.customExclusionsPattern = customExclusions.Replace("\r\n", "|").Replace("\n", "|");
        }



        public int BlankLine
        {
            get
            {
                ExsureCalculated();
                return blankLine;
            }
        }
        public int CustomExclusionLine
        {
            get
            {
                ExsureCalculated();
                return customExclusionLine;
            }
        }


        public int CodeLine
        {
            get
            {
                return TotalLine - BlankLine - CustomExclusionLine;
            }
        }

        public int TotalLine
        {
            get
            {
                return Lines.Length;
            }
        }

        private void ExsureCalculated()
        {
            if (isCalculated == false)
            {
                Count();
                isCalculated = true;
            }
        }

        private void Count()
        {
            Regex blankLineReg = new Regex(@"^\s*$");
            Regex customExclusionLineReg = new Regex(customExclusionsPattern);

            this.blankLine = 0;
            this.customExclusionLine = 0;

            foreach (string line in Lines)
            {
                if (notCountBlankLine && blankLineReg.IsMatch(line))
                {
                    blankLine++;
                }
                else if (customExclusionsPattern.Length > 0 && customExclusionLineReg.IsMatch(line))
                {
                    customExclusionLine++;
                }
            }
        }

        public string FilePath
        {
            get
            {
                return filePath;
            }
        }

        private string[] Lines
        {
            get
            {
                if (lines == null)
                {
                    lines = GetFileLines(filePath);
                }
                return lines;
            }
        }
        
        /// <summary>
        /// 获取文件的所有行
        /// </summary>
        /// <param name="file"></param>
        /// <returns></returns>
        private static string[] GetFileLines(string file)
        {
            using (FileStream fs = new FileStream(file, FileMode.Open, FileAccess.Read))
            {
                StreamReader sr = new StreamReader(fs, Encoding.Default);
                string[] lines = sr.ReadToEnd().Split(new string[] { "\r\n", "\n" }, StringSplitOptions.None);
                return lines;
            }
        }
    }
}


运行效果图:

统计源代码行数的工具(含源码)_第1张图片

 

下载地址:csdn下载地址

你可能感兴趣的:(源代码,行数,统计软件)