github地址:https://github.com/PhilippeJLL/WordCount
※写在前面:开发使用的操作系统:macOS 推荐运行git上提交的jar,我自己的测试均在mac下利用jar进行;
Java版本:Java SE Development Kit 9.0.4 低版本的JDK可能无法运行提交的exe,会出现如下报错:
"...has been compiled by a more recent version of the Java Runtime (class file version 53.0),
this version of the Java Runtime only recognizes class file versions up to 52.0..."
需求有一处微小的变化,在利用“-s”命令遍历文件夹时,我的程序要求必须提供该文件夹的路径(绝对路径和相对路径均可,但必须显式输入)。
解题思路:主要函数为计数的方法,也就是程序的核心;其次需要用到文件操作相关的方法;因为要用命令行参数来执行程序,所以需要了解命令行的相关对象和方法;
最后参照作业所给出的用exe4j生成可执行文件的博客来打包成.exe文件。
对于计数,参考百度文库中的一个实验报告https://wenku.baidu.com/view/a16b2dd8b307e87101f696ed.html
对于文件操作的方法,参考CSDN的一篇文章http://blog.csdn.net/a909301740/article/details/52574602
对于命令行参数的使用,参考了百度知道的一个答案https://zhidao.baidu.com/question/1957633019096013060.html
比较重要的问题参考就来自于这几个资料,
后来为了扩展功能,又参考了关于递归遍历文件夹的资料https://www.cnblogs.com/azhqiang/p/4596793.html
PSP表格:
PSP2.1 |
PSP阶段 |
预估耗时 (分钟) |
实际耗时 (分钟) |
Planning |
计划 |
60 | 100 |
· Estimate |
· 估计这个任务需要多少时间 |
4天 | 5天 |
Development |
开发 |
3天 | 5天 |
· Analysis |
· 需求分析 (包括学习新技术) |
1天 | 2天 |
· Design Spec |
· 生成设计文档 |
30 | 30 |
· Design Review |
· 设计复审 (和同事审核设计文档) |
30 | 30 |
· Coding Standard |
· 代码规范 (为目前的开发制定合适的规范) |
20 | 10 |
· Design |
· 具体设计 |
300 | 500 |
· Coding |
· 具体编码 |
2天 | 3天 |
· Code Review |
· 代码复审 |
60 | 60 |
· Test |
· 测试(自我测试,修改代码,提交修改) |
50 | 50 |
Reporting |
报告 |
300 | 300 |
· Test Report |
· 测试报告 |
50 | 50 |
· Size Measurement |
· 计算工作量 |
10 | 10 |
· Postmortem & Process Improvement Plan |
· 事后总结, 并提出过程改进计划 |
240 | 240 |
合计 |
3天零15小时 | 5天零20小时 |
-
-
-
- 主函数main(),会在-s命令处理文件夹时调用traverseFolder(),或在处理单文件是调用infile()和outfile();
- 用于计数的函数wc(),被调用;
- 用于递归文件的函数traverseFolder(),调用writer()、infile()和outfile(),以输出每个文件的路径和统计结果;
- 用于给文件追加内容的函数writer(),被调用;
- 用于确定输入的文件的函数infile(),被调用;
- 用于确定输出的文件的函数outfile(),会调用writer()以追加内容。
-
-
程序流程仍然为获取命令行参数、打开输入文件、计算、输出结果。
1 public static void wc(InputStream f) throws IOException { 2 int c = 0; 3 boolean lastNotWhite = false; 4 String whiteSpace = " \t\n\r"; 5 while ((c = f.read()) != -1) { 6 chars++; 7 if (c == '\n') { 8 lines++; 9 } 10 if (whiteSpace.indexOf(c) != -1) { 11 if (lastNotWhite) { 12 words++; 13 } 14 lastNotWhite = false; 15 } 16 else lastNotWhite = true; 17 } 18 }
这部分核心代码因无从下手,参考了文章前面所列的那个实验报告[1]中计算的代码。实现的主要方法就是通过传入一个InputStream,然后通过FileInputStream中的read()方法,每次读取一个字节,并通过判断字符内容(即是否出现转义字符)来判断是否为新单词和新行;
②关于命令行参数的代码:
1 int argc = args.length; 2 String filepath = null; 3 String outpath = null; 4 for (int i = 0; i < argc; i++) { 5 if (args[i].equals("-o")) { 6 filepath = args[i - 1]; 7 outpath = args[i + 1]; 8 break; 9 } 10 else { 11 filepath = args[argc -1]; 12 outpath = "result.txt"; 13 } 14 } 15 16 17 boolean cf, wf, lf; 18 cf = wf = lf = false; 19 for (int i = 0; i < argc; i++) { 20 switch (args[i]) { 21 case "-c": 22 cf = true; 23 break; 24 case "-w": 25 wf = true; 26 break; 27 case "-l": 28 lf = true; 29 break; 30 default: 31 break; 32 } 33 }
因为这是第一次用命令行参数,暂且把它列为重要代码,主要是利用args.length()这个方法来获取参数个数,用args[]数组中的元素来获取参数的具体内容;
重要的是判断好每个参数,避免出现参数缺失(如-o未匹配文件路径),参数传错的情况。
③递归调用遍历文件夹的代码:
1 public static void traverseFolder(String path, String outpath) throws IOException{ 2 File file = new File(path); 3 if (file.exists()) { 4 File[] files = file.listFiles(); 5 if (files.length == 0) { 6 System.out.println("the folder is empty."); 7 return; 8 } 9 else { 10 wrf = true; 11 for (File file2 : files) { 12 if (file2.isDirectory()) { 13 writer(outpath, file2.getAbsolutePath() + "\n"); 14 traverseFolder(file2.getAbsolutePath(), outpath); 15 } 16 else { 17 writer(outpath, file2.getAbsolutePath() + "\n"); 18 infile(file2.getAbsolutePath()); 19 outfile(outpath); 20 } 21 } 22 } 23 } 24 else { 25 System.out.println("the folder/file is not exist."); 26 } 27 }
这部分代码参考了网上的一篇文章[5],遍历文件和文件夹时用到的方法参考了文章,同时加入了路径的输出并调用infile()和outfile()来进行对文件的统计处理和输出结果。
java -jar ./wc.jar -c ./test1.cpp //程序在相对路径下创建result.txt并写入字符统计结果 java -jar ./wc.jar -c ./test1.cpp -o ./test.txt //程序将字符统计结果写入text.txt java -jar ./wc.jar -w -l -c ./test1.cpp //程序在相对路径下创建result.txt并写入字符、单词、行统计结果 java -jar ./wc.jar -w -l -c ./test1.cpp -o ./test.txt //程序将字符、单词、行统计结果写入text.txt java -jar ./wc.jar -l -w /Users/travis/test2.cpp -o /Users/travis/Desktop/test2.txt //程序将单词、行统计结果写入位于桌面的text2.txt
java -jar ./wc.jar -c ./test2.txt //测试输入txt文件 java -jar ./wc.jar -c ./test.docx //测试输入word文档 java -jar ./wc.jar -c ./wc.java //测试输入.java源文件
java -jar ./wc_1.jar -c ./a.txt //测试统计含有中文字符的文件
java -jar ./wc_1.jar -c ./test.cpp // 测试含有注释符“//”、换行符“\n”的代码
[1]Java实验六统计文件中字符数、单词数和行数https://wenku.baidu.com/view/a16b2dd8b307e87101f696ed.html
[2]FileInputStream读取文件数据的两种方式http://blog.csdn.net/a909301740/article/details/52574602
[3]java中如何通过命令行来传递参数https://zhidao.baidu.com/question/1957633019096013060.html
[4]Java使用递归找出某目录下的所有子目录以及子文件https://www.cnblogs.com/wangtianze/p/6690644.html
[5]JAVA遍历文件夹下的所有文件(递归调用和非递归调用)https://www.cnblogs.com/azhqiang/p/4596793.html