今天突然想统计一下代码的行数,没有想太多就动手写了一个。写完才发现是重复造轮子,网上已经有这样的工具了。既然造了,那就共享出来,能用得上的,就用用。
开发环境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; } } } }
运行效果图:
下载地址:csdn下载地址