今天突然想统计一下代码的行数,没有想太多就动手写了一个。写完才发现是重复造轮子,网上已经有这样的工具了。既然造了,那就共享出来,能用得上的,就用用。
开发环境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 codeFileCounterList =
GetAllFilesStatistics(txtCodePath.Text, cbSeacheSubFolder.Checked, txtSourceFileExtension.Text, cbNoEmptyLine.Checked, txtOutOfStatistics.Text);
FillToGrid(codeFileCounterList, txtCodePath.Text);
}
private void FillToGrid(List 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;
}
///
/// 获取所有文件的统计信息
///
/// 源代码文件目录
/// 是否获取子文件夹的文件。true,获取所有子文件夹的文件
/// 要获取的文件的扩展名。多个扩展名用“|”分割,如:*.txt|*.cs 。 ""、"*","*.*"表示所有文件
/// 不统计空行
/// 用户定义的排除行规则。一个规则一行。
///
private List GetAllFilesStatistics(string sourceFloder, bool isSeachSubFolder, string fileExtensions, bool notCountBlankLine, string customExclusions)
{
List codeFileCounterList = new List();
foreach (string fileName in GetDirectoryFiles(sourceFloder, fileExtensions, isSeachSubFolder))
{
codeFileCounterList.Add(new CodeFileCounter(fileName, notCountBlankLine, customExclusions));
}
return codeFileCounterList;
}
///
/// 获取源文件夹下的所有文件.
///
/// 源代码文件目录
/// 要获取的文件的扩展名。多个扩展名用“|”分割,如:*.txt|*.cs 。 ""、"*","*.*"表示所有文件
/// 是否获取子文件夹的文件。true,获取所有子文件夹的文件
///
private static List GetDirectoryFiles(string sourceFoloder, string fileExtensions, bool isSeachSubFolder)
{
string[] extensions = ConvertExtensionsToArray(fileExtensions);
List fileList = new List();
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;
}
///
/// 将*.cs|*.cpp转化为["cs","cpp"]这种类型的数组.
///
///
///
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; //是否计算过
///
/// 构造数组代码文件统计对象
///
/// 代码文件路径
/// 不统计空白行
/// 用户自定义排除项。每一行代表一个排除项
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;
}
}
///
/// 获取文件的所有行
///
///
///
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下载地址