WordCount的实现
学号:201631062517
一本文代码
Github代码下载链接:https://gitee.com/yuanzessrs/WordCount
二:功能概述:
2.1.1 基本功能
wc.exe -c file.c //返回文件 file.c 的字符数
wc.exe -w file.c //返回文件 file.c 的单词总数
wc.exe -l file.c //返回文件 file.c 的总行数
wc.exe -o outputFile.txt //将结果输出到指定文件outputFile.txt
2.1.2 扩展功能
wc.exe -s //递归处理目录下符合条件的文件
[file_name]: 文件或目录名,可以处理一般通配符
三:项目设计
3.1 命令行参数
参数的形式:参数-o 必须紧跟 输出文件路径 其他命令位置可变 解析文件路径只能有一个
格式: WordCount.exe [操作] [文件路径|通配符路径]
参数空格隔开
程序入口会自动读取空格分开的参数 并存入Args数组
-c //返回文件 的字符总数
-w //返回文件 的单词总数
-l //返回文件 的总行数
-s //是否递归处理目录下 所有文件或 通配符文件
-h //显示帮助
-o 输出文件路径 //将结果输出到指定文件
四:代码实现
主函数
using System; using System.Collections.Generic; using System.IO; namespace WordCount { class Program { static void Main(string[] args) { // 解析命令行参数数组. ArgsUtil.ArgsParse(args); // 检查 命令行参数的正确性 正确就执行. if(OperationUtil.Check()) OperationUtil.Run(); } } }
参数处理类
using System; using System.Collections; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace WordCount { class ArgsUtil { // 解析参数数组后 得到的操作集合. public static ArrayList OperationList = new ArrayList(); // 解析文件路径. public static String FilePath = ""; // 结果输出文件路径. public static String OutputFilePath = ""; public static bool OwithOF = true; public static bool ArgsError = false; public static bool FilePathNull = false; public static void ArgsParse(string[] args) { int count = 0; // 遍历参数数组. for (int x = 0; x < args.Length; x++) { // 如果参数是 -c 操作. if (args[x].ToLower().Equals("-c")) { if(!OperationList.Contains("-c")) OperationList.Add("-c"); } // 如果参数是 -w 操作. else if (args[x].ToLower().Equals("-w")) { if (!OperationList.Contains("-w")) OperationList.Add("-w"); } // 如果参数是 -l 操作. else if (args[x].ToLower().Equals("-l")) { if (!OperationList.Contains("-l")) OperationList.Add("-l"); } // 如果参数是 -s 操作. else if (args[x].ToLower().Equals("-s")) { if (!OperationList.Contains("-s")) OperationList.Add("-s"); } // 如果参数是 -h 操作. else if (args[x].ToLower().Equals("-h")) { if (!OperationList.Contains("-h")) OperationList.Add("-h"); } // 如果参数是 -o 操作. else if (args[x].ToLower().Equals("-o")) { if (!OperationList.Contains("-o")) OperationList.Add("-o"); if (x + 1 < args.Length) { // 判断-o 后面是不是文件路径 -o只能跟输出文件路径. if (args[x + 1].ToLower().Equals("-c") || args[x + 1].ToLower().Equals("-w") || args[x + 1].ToLower().Equals("-o") || args[x + 1].ToLower().Equals("-l") || args[x + 1].ToLower().Equals("-s") || args[x + 1].ToLower().Equals("-h")) { OwithOF = false; } else { OutputFilePath = args[x + 1]; x++; } } else { OwithOF = false; } } // 如果参数 不是以上几个操作 则是文件路径. else { FilePath = args[x].Trim(); count++; } } //参数数组中是否存在 文件路径 标志. if (count == 0) { FilePathNull = true; } //参数数组中是否存在 其他非法操作符. if (count>1) { ArgsError = true; } } } }
文件操作类
using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Text; using System.Threading.Tasks; namespace WordCount { class FileUtils { /// <summary> /// 返回当前目录下满足 pattern的 文件. /// </summary> /// <param name="pattern"></param> /// <returns></returns> public static List<String> Glob(String pattern) { String directoryName = Path.GetDirectoryName(pattern); // 假如没有目录 指定当前目录. if(directoryName.Equals("")) { directoryName = Environment.CurrentDirectory; } return new List<string>(Directory.GetFiles(directoryName, Path.GetFileName(pattern))); } /// <summary> /// 返回当前目录下满足 pattern的 文件(递归所有子文件夹). /// </summary> /// <param name="path"></param> /// <param name="pattern"></param> /// <returns></returns> public static List<String> SGlob(String path,String pattern) { List<String> result = new List<string>(); result.AddRange(Directory.GetFiles(path, pattern)); foreach(String sub in Directory.GetDirectories(path)) { result.AddRange(SGlob(Path.Combine(path,sub),pattern)); } return result; } /// <summary> /// 通过传入的参数 打开文件并读取文件内容. /// </summary> /// <param name="path"></param> /// <returns></returns> public static String ReadFile(String path) { try { StreamReader sr = new StreamReader(path); String content = ""; content = sr.ReadToEnd(); sr.Close(); return content; } catch (Exception e) { Console.WriteLine("文件路径出错"); return null; } } /// <summary> /// 将传入的结果写入到指定的文件中. /// </summary> /// <param name="OutputFile"></param> /// <param name="result"></param> public static void WriteFile(String OutputFile,String result) { result = "输出结果到文件:" + OutputFile+"\r\n"+result; try { StreamWriter sw = new StreamWriter(OutputFile); sw.Write(result); sw.Flush(); sw.Close(); } catch (Exception e) { Console.WriteLine("文件路径出错"); } } /// <summary> /// 根据文本字符串内容 统计文本字符长度 /// </summary> /// <param name="Content"></param> /// <returns></returns> public static int CountChars(String Content) { return Content.Length; } /// <summary> /// 根据文本字符串内容 统计文本单词数. /// </summary> /// <param name="Content"></param> /// <returns></returns> public static int CountWords(String Content) { String[] SpaceSplit = Content.Split(' '); // Console.WriteLine("空格分隔数:"+SpaceSplit.Length); int words = 0; for (int x = 0; x < SpaceSplit.Length; x++) { if (SpaceSplit[x].Trim().Length != 0) { String[] CommaSplit = SpaceSplit[x].Split(','); // Console.WriteLine("逗号分隔数:"+ CommaSplit.Length); for (int y = 0; y < CommaSplit.Length; y++) { if (CommaSplit[y].Trim().Length != 0) words += 1; } } } return words; } /// <summary> /// 根据文本字符串内容 统计文本行数. /// </summary> /// <param name="Content"></param> /// <returns></returns> public static int CountLines(String Content) { // 字符串索引 int index = 0; // 行数 int lineCount = 0; if (Content.Trim().Length != 0) { while (index < Content.Length) { // 通过判断文本中 \n 的个数来判断行数. if (Content[index] == '\n') { lineCount++; } index++; } lineCount++; } return lineCount; } } }
参数功能类
using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Text; using System.Threading.Tasks; namespace WordCount { class OperationUtil { /// <summary> /// 根据命令行参数处理结果,检查命令行参数的正确性. /// </summary> public static bool Check() { bool IsOk = true; if(!(ArgsUtil.OperationList.Count==1&& ArgsUtil.OperationList[0].Equals("-h"))) { if (ArgsUtil.OperationList.Count != 0) { // 判断是否 -o 后面有输出文件路径. if (!ArgsUtil.OwithOF) { Console.WriteLine("参数错误: -o 后面没有 输出文件路径"); IsOk = false; } // 检查 解析文件路径是否为空 if (ArgsUtil.FilePathNull) { Console.WriteLine("参数错误: 没有 解析文件路径"); IsOk = false; } else { if (FileUtils.Glob(ArgsUtil.FilePath).Count==0) { Console.WriteLine("参数错误: 解析文件非法"); IsOk = false; } } // 检查 命令行参数是否有非法字符. if (ArgsUtil.ArgsError) { Console.WriteLine("参数错误: 参数中含有非法字符\n请通过 -h 查看帮助"); IsOk = false; } } } return IsOk; } /// <summary> /// 当命令行参数检查完成后,正确无误则开始处理参数中的操作. /// </summary> public static void Run() { // 存储结果信息的字符串. String result = ""; // 待处理文件列表. List<String> FileList=new List<string>(); // 判断文件路径是否为空. if(!ArgsUtil.FilePathNull) { // 判断是否需要递归目录. if (ArgsUtil.OperationList.Contains("-s")) { String path = Path.GetDirectoryName(ArgsUtil.FilePath); String filename = Path.GetFileName(path); FileList = FileUtils.SGlob(path, filename); } else { FileList = FileUtils.Glob(ArgsUtil.FilePath); } //遍历文件列表 处理每个文件. foreach (String file in FileList) { // 当前文件内容. String content; foreach (String arg in ArgsUtil.OperationList) { content = FileUtils.ReadFile(file); // 判断文件是否打开成功. if (content != null) { if (arg.Equals("-c")) { Console.WriteLine("文件名:" + file + " 字符数:" + FileUtils.CountChars(content)); result += "文件名:" + file + " 字符数:" + FileUtils.CountChars(content) + "\r\n"; } if (arg.Equals("-w")) { Console.WriteLine("文件名:" + file + " 单词数:" + FileUtils.CountWords(content)); result += "文件名:" + file + " 单词数:" + FileUtils.CountWords(content) + "\r\n"; } if (arg.Equals("-l")) { Console.WriteLine("文件名:" + file + " 行数:" + FileUtils.CountLines(content)); result += "文件名:" + file + " 行数:" + FileUtils.CountLines(content) + "\r\n"; } if (arg.Equals("-s") || arg.Equals("-h") || arg.Equals("-o")) { continue; } } } } } // 判断是否需要输出结果到文件. if (ArgsUtil.OperationList.Contains("-o")) { if (result.Trim().Length != 0) FileUtils.WriteFile(ArgsUtil.OutputFilePath, result); } // 判断是否需要帮助. if (ArgsUtil.OperationList.Contains("-h")) { help(); } Console.Read(); } /// <summary> /// 帮助函数 /// </summary> public static void help() { // 输出 help Console.WriteLine("格式: WordCount.exe [操作] [文件路径|通配符路径]"); Console.WriteLine("-c //返回文件 的字符总数"); Console.WriteLine("-w //返回文件 的单词总数"); Console.WriteLine("-l //返回文件 的总行数"); Console.WriteLine("-s //是否递归处理目录下 所有文件或 通配符文件"); Console.WriteLine("-h //显示帮助"); Console.WriteLine("-o 输出文件路径 //将结果输出到指定文件\n\n"); } } }
五:测试用例
等价类划分
基于等价类划分的测试用例设计:
六:运行结果
文件内容
运行结果
七、总结
合理使用逻辑清晰的算法、可以少写代码。尽可能把功能分开封装,互不影响,方便修改