Implementation of WC in JAVA

Implementation of WC in JAVA

github地址

相关要求

  • 基本功能

    1. -c [文件名] 返回文件的字符数 (实现)
    2. -w [文件名] 返回文件的词的数目 (实现)
    3. -l [文件名] 返回文件的行数 (实现)
  • 扩展功能
    1. -s 递归处理目录下符合条件的文件。 (实现)
    2. -a 返回更复杂的数据(代码行/空行/注释行)(实现)
    3. 支持各种文件的通配符(*,?) (实现)
  • 高级功能

    1.支持图形化界面 (实现)


PSP

PSP2.1 Personal Software Process Stages 预估耗时(分钟) 实际耗时(分钟)
Planning 计划
· Estimate · 估计这个任务需要多少时间 30 35
Development 开发
· Analysis · 需求分析 (包括学习新技术) 180 120
· Design Spec · 生成设计文档 120 60
· Design Review · 设计复审 (和同事审核设计文档) 60 40
· Coding Standard · 代码规范 (为目前的开发制定合适的规范) 100 60
· Design · 具体设计 180 120
· Coding · 具体编码 300 360
· Code Review · 代码复审 60 30
· Test · 测试(自我测试,修改代码,提交修改) 120 60
Reporting 报告 60 30
· Test Report · 测试报告 60 60
· Size Measurement · 计算工作量 60 30
· Postmortem & Process Improvement Plan · 事后总结, 并提出过程改进计划 20 15
合计 1290 1020

设计说明

graph LR
A[MainWork] --> B(controller)
A[MainWork] --> C(UI)
B(controller) --> D(WordCounter)
B(controller) --> E(FileFinder)
C(UI) --> F(NewJFrame)

graph TB
A[WordCounter] --> B[CharacterSum]
A[WordCounter] --> c[Rows_Number]
A[WordCounter] --> d[word_cal]
A[WordCounter] --> e[isCodeLine]
A[WordCounter] --> f[isEmptyLine]
A[WordCounter] --> h[ScanFileinRecursion]
A[WordCounter] --> I[getRelatedFiles]
e[isCodeLine] --> g[isAnnotationLine]
f[isEmptyline] --> g[isAnnotationLine]

  • MainWork: 通过输入的参数来调用模块WordCounter中的方法实现基本要求和扩展要求,以及调用实现高级要求中的图形化界面
  • controller: 基本功能与扩展功能模块包
  • Word Counter:实现-c 统计文件字符数方法,实现-w 统计文件单词数方法,实现-l 统计文件行数,以及实现 -a中统计文件注释行,代码行,空行和-s的递归处理目录下文件的命令参数。
  • FileFinder:实现支持处理文件名通配符
  • UI(图形界面):NewJFrame 是为了实现处理-x参数传入时所设计的JAVA Swing图形化界面

解题思路与关键代码

代码

  1. -c 统计文件字符数

    解题思路 -FileReader读入文件,读入时计数器同时递增即可记录文件字符数目,单文件不存在计数器置为-1,与空文件区别开

      public static int CharacterSum(File file) throws IOException {
            int count_Char = 0;
            if(!file.exists())
            {
                count_Char = -1;
                return count_Char;
            }
            FileReader fr = new FileReader(file);
            while(fr.read()!=-1)
            {
                count_Char++;
            }
            return count_Char;
    
        }
    
  2. -l 统计文件行数

    解题思路 通过文件读入方式以字符缓冲输入流读入,缓冲字符,从而实现以行读取并计数器计算出行数,文件不存在时同上处理

     public static int Rows_number(File file) throws IOException {
            int count_Row = 0;
            if(!file.exists())
            {
                count_Row = -1;
            }
            else
            {
                FileReader fr = new FileReader(file);
                BufferedReader br = new BufferedReader(fr);
    
                String s = null;
                while((s=br.readLine())!=null)
                {
                    count_Row++;
                }
            }
            return count_Row;
        }
    
  3. -w 统计文件单词数

    解题思路 学习了正则表达式,readLine每行读入文件与正则表达式匹配从而计算出单词数,文件不存在同上处理

    public static int word_cal(File file) throws IOException {
            int count_Word = 0;
            if(!file.exists())
            {
                count_Word = -1;
            }
            else
            {
                FileReader fr = new FileReader(file);
                BufferedReader br = new BufferedReader(fr);
                String s = null;
                while((s=br.readLine())!=null)
                {
                    String reg = "\\d+.\\d+|\\w+";
                    Matcher mat = Pattern.compile(reg).matcher(s);
                    while(mat.find())
                    {
                        count_Word++;
                    }
    
                }
            }
            return count_Word;
        }
    
    
  4. -a 统计文件空行,代码行,注释行

    解题思路与代码

    • 空行统计:根据需求,空行不得多于一个可显示字符,readLine读入文件每行字符串.trim()去掉空格和格式控制符,若字符串长度不大于1则空行计数器加一,文件不存在同上处理
    public static int isEmptyLine(File file) throws IOException {
            int count_EmptyLine = 0;
            if(!file.exists())
            {
                count_EmptyLine = -1;
            }
            else
            {
    
                FileReader fr = new FileReader(file);
                BufferedReader br = new BufferedReader(fr);
                String s = null;
                while((s=br.readLine())!=null)
                {
                    if(s.trim().length()<=1){
                        count_EmptyLine++;
                    }
                }
    
            }
            return count_EmptyLine;
        }
    
    • 代码行统计:将文件readLine读入,每行字符串.trim()去掉空格,格式控制符之后通过正则表达式将注释符号//、/**/等匹配并删除,并对某些特殊情况进行处理,保留换行符,并append到StringBuffer中,最后将StringBuffer放入一个字符缓冲器当中并统计行数,即可得出代码行数目。文件不存在同上处理
     public static int isCodeLine(File file) throws IOException {
            int count_CodeLine = 0;
            if(!file.exists())
            {
                count_CodeLine = -1;
            }
            else {
                FileReader fr = new FileReader(file);
                BufferedReader br = new BufferedReader(fr);
                String s = null;
                Pattern p = Pattern.compile("\\/\\/[^\\n]*|\\/\\*([^\\*^\\/]*|[\\*^\\/*]*|[^\\**\\/]*)*\\*+\\/");
                String tmp = null;
                StringBuffer sb = new StringBuffer();
                String target = null;
                while ((s = br.readLine()) != null) {
                    s = s.trim();
                    int flag = 0;
                    int pos = 0;
                    for (int i = 1; i < s.length(); i++) {
                        if ((i+1)<s.length()-1&&s.charAt(i) == ‘/‘ && (s.charAt(i + 1) == ‘/‘ || s.charAt(i + 1) == ‘*‘)) {
                            pos = i;
    
                            if(s.charAt(i)==‘/‘&&s.charAt(i+1)==‘/‘)
                            {
                                sb.append(s,0,i);
                                sb.append("\n");
                            }
                            else if(s.charAt(i+1)==‘*‘&& !s.substring(i).contains("*/"))
                            {
                                String t = (String) s.subSequence(0, i);
                                sb.append(t);
                                sb.append("\n");
                                sb.append(s.substring(i));
                                sb.append("\n");
                            }
                            else if(s.charAt(i+1)==‘*‘&& s.substring(i).contains("*/"))
                            {
                                Matcher m = p.matcher(s);
                                tmp = m.replaceAll("");
                                sb.append(tmp);
                                sb.append("\n");
                                flag = 1;
                                break;
                            }
                            flag = 1;
    
                        }
    
                    }
                    if (flag == 0) {
                        if (s.length() > 1 && s.substring(0, 1).equals("*/")) {
    
                            sb.append("*/");
                            sb.append("\n");
                            sb.append(s.substring(2));
                            sb.append("\n");
                        } else {
                            sb.append(s);
                            sb.append("\n");
    
                    }
                        }
    
                    }
                }
                br.close();
                target = sb.toString();
                Matcher mat = p.matcher(target);
                String res = null;
                res = mat.replaceAll("");
                BufferedReader context = new BufferedReader(new StringReader(res));
                while((tmp=context.readLine())!=null)
                {
    
                    if(tmp.trim().length()>1)
                    {
                        count_CodeLine++;
                    }
                }
    
            }
            return count_CodeLine;
        }
    
    
    • 注释行数目:通过以上对总行数,空行数,代码行数目的计算,则可以通过调用以上方法可得出注释行数目=总行数-空行数-代码行数目
            public static int isAnnotationLine(File file) throws IOException {
                int count_Annotation = 0;
                if(!file.exists())
                {
                    count_Annotation = -1;
                }
                else
                {
                    count_Annotation = Rows_number(file) - isEmptyLine(file) - isCodeLine(file);
                }
                return count_Annotation;
            }
    
  5. -s 递归处理目录下符合条件的文件。

    解题思路 将非根目录文件夹的文件路径名通过递归方法放入List中

     public static List<String> ScanFileInRecursion(File file)
        {
    
            if(!file.isDirectory())
            {
                System.out.println("非合法目录文件夹!请重新输入!");
            }
            else
            {
                File[] files = file.listFiles();
                for(int i=0;i<files.length;i++)
                {
                    if(files[i].isDirectory())
                    {
    
                        ScanFileInRecursion(files[i]);
                    }
                    else
                    {
                        System.out.println(files[i].getAbsolutePath());
                        filepath.add(files[i].getAbsolutePath());
                    }
                }
    
            }
            return filepath;
        }
    
  6. 支持各种文件的通配符(*,?)

    解题思路 使用的是JDK 1.7,Files.walkFileTree,经过学习发现比File类的遍历效率要高很多,FileFinder类继承FileVisitor适配器SimpleFileVisitor

    FileFinder:

    public class FileFinder extends SimpleFileVisitor<Path> {
        private final PathMatcher matcher;
        private List<Path> matchedPaths = new ArrayList<Path>();
        private List<Path> matchedAbPaths = new ArrayList<Path>();
        FileFinder(String pattern)
        {
            matcher = FileSystems.getDefault().getPathMatcher("glob:"+ pattern);
        }
    
        void match(Path file)
        {
            Path name = file.getFileName();
            if(name!=null && matcher.matches(name)){
                matchedPaths.add(name);
    
                matchedAbPaths.add(file.toAbsolutePath());
            }
        }
        @Override
        public FileVisitResult visitFile(Path file,BasicFileAttributes attrs)
        {
            match(file);
            return  CONTINUE;
        }
    
        @Override
        public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs)
        {
            match(dir);
            return CONTINUE;
        }
    
        @Override
        public FileVisitResult visitFileFailed(Path file, IOException exc)
        {
            System.err.println(exc);
            return  CONTINUE;
        }
        public int getTotalMatches()
        {
            return matchedPaths.size();
        }
        public Collection<Path> getMatchedPaths()
        {
            return matchedPaths;
        }
        public List<Path> getMatchedAbPaths()
        {
            return matchedAbPaths;
        }
    
    }
    

    WordCounter的getRelatedFiles方法:

            public static List<Path> getRelateFiles(String filepath) throws IOException {
                FileFinder finder = new FileFinder(filepath);
                Files.walkFileTree(Paths.get(System.getProperty("user.dir")),finder);
    
                Collection<Path> Absolutematched = finder.getMatchedAbPaths();
                return (List<Path>) Absolutematched;
    }
    
  7. -x 图形化界面功能

    解题思路 根据Java的Swing设计界面,通过filechooser来选择文件进行wordcount功能演示。

    界面设计部分具体太多则不贴出,下面只贴按钮监听事件部分:

    private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) throws IOException, IOException {
            // TODO add your handling code here:
            jTextArea1.setText("");
            JFileChooser jfc=new JFileChooser();
            jfc.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES );
            jfc.showDialog(new JLabel(), "选择");
            File file=jfc.getSelectedFile();
            if(file.isDirectory()){
                System.out.println("文件夹:"+file.getAbsolutePath());
            }else if(file.isFile()){
                System.out.println("文件:"+file.getAbsolutePath());
            }
            System.out.println(jfc.getSelectedFile().getName());
            BufferedReader br = new BufferedReader(new FileReader(file));
            String s = null;
            while((s=br.readLine())!=null)
            {
                jTextArea1.append(s+"\n");
            }
    
            br.close();
            int char_count = CharacterSum(file);
            int word_count = word_cal(file);
            int line_cunt = Rows_number(file);
            int empty_line = isEmptyLine(file);
            int code_line = isCodeLine(file);
            int annotate_line = isAnnotationLine(file);
    
            if(char_count==-1||word_count==-1||line_cunt==-1||empty_line==-1||code_line==-1||annotate_line==-1)
            {
                chara.setText("字符数:0");
                jLabel2.setText("单词数:0");
                jLabel3.setText("总行数:0");
                jLabel4.setText("空行数:0");
                jLabel5.setText("注释行:0");
                jLabel6.setText("代码行:0");
            }
            else{
                chara.setText("字符数: "+char_count);
                jLabel2.setText("单词数: "+word_count);
                jLabel3.setText("总行数: "+line_cunt);
                jLabel4.setText("空行数: "+empty_line);
                jLabel5.setText("注释行: "+annotate_line);
                jLabel6.setText("代码行: "+code_line);
            }
    
        }
    

测试

命令行输入参数测试-c -w -l -a:

测试-s:

测试 -x:

测试文本文件:

#include<bits/stdc++.h>
using namespace std;

typedef long long ll;
const int mod = 1e9+7;
void exgcd(ll a,ll b,ll &x,ll &y)
{
	/*
		欧几里得
	*/
	if(b==0)
	{
		x = 1;
		y = 0;
		return ;
	}
	ll x1,y1;
	exgcd(b,a%b,x1,y1);
	x = y1;
	y = x1-(a/b)*y1;
}
int main()
{
	//code here
	ll n,m;
	while(cin>>n>>m)
	{
		ll res = 1;
		for(ll i=1;i<=n+m-4;i++)
			res  = (res*i)%mod;
		for(ll i=1;i<=n-2;i++)
		{
			ll x,y;
			exgcd(i,mod,x,y);
			x = (x%mod+mod)%mod;
			res = (res*x)%mod;
		}
		for(ll i=1;i<=m-2;i++)
		{
			ll x,y;
			exgcd(i,mod,x,y);
			x = (x%mod+mod)%mod;
			res = (res*x)%mod;
		}
		res = (res%mod+mod)%mod;
		cout<<res<<endl;
	}
	return 0;
}

代码覆盖率


小结

在设计完成该项目的时候收获很多,认识到对自己个人项目的设计的不足,包括时间的分配不科学,以及设计过程中对某些细节没有仔细考虑清楚,就开始着手程序,导致后面做了很多调整,让我觉得以后自身在学习开发时要多在前期设计下多点功夫。同时深刻了解到自己代码的不规范所带的问题。这次课程项目的开发用到了Java开发,过程中也学习到了不少新的东西,对以前学的东西有了进一步的了解,包括对如何通配符支持的研究和对正则表达式的深一步理解运用。希望自己能够在以后的项目设计和编写中通过学习和反省从而达到高效。

原文地址:https://www.cnblogs.com/laomiXD/p/9636161.html

时间: 2024-08-30 18:07:07

Implementation of WC in JAVA的相关文章

个人项目WC(java实现)

WC个人项目(JAVA实现) 一.Github地址:https://github.com/Gvonte/WC.exe 二.PSP表格 PSP2.1 Personal Software Process Stages 预估耗时(分钟) 实际耗时(分钟) Planning 计划 30 28 · Estimate · 估计这个任务需要多少时间 30 28 Development 开发 1012 1001 · Analysis · 需求分析  52 45 · Design Spec · 生成设计文档 30

java实现wc

github项目传送门:https://github.com/yanghuipeng/wc 项目要求 wc.exe 是一个常见的工具,它能统计文本文件的字符数.单词数和行数.这个项目要求写一个命令行程序,模仿已有wc.exe 的功能,并加以扩充,给出某程序设计语言源文件的字符数.单词数和行数. 实现一个统计程序,它能正确统计程序文件中的字符数.单词数.行数,以及还具备其他扩展功能,并能够快速地处理多个文件. 基本功能列表 -c    [文件名]  返回文件的字符数 -w   [文件名]  返回文

Java Interview Reference Guide--reference

Part 1 http://techmytalk.com/2014/01/24/java-interview-reference-guide-part-1/ Posted on January 24, 2014 by Nitin Kumar JAVA Object Oriented Concepts Java in based on Object Oriented concepts, which permits higher level of abstraction to solve any p

Java Secure Socket Extension (JSSE) Reference Guide

Skip to Content Oracle Technology Network Software Downloads Documentation Search Java Secure Socket Extension (JSSE) Reference Guide This guide covers the following topics: Skip Navigation Links Introduction Features and Benefits JSSE Standard API S

Spark:用Scala和Java实现WordCount

为了在IDEA中编写scala,今天安装配置学习了IDEA集成开发环境.IDEA确实很优秀,学会之后,用起来很顺手.关于如何搭建scala和IDEA开发环境,请看文末的参考资料. 用Scala和Java实现WordCount,其中Java实现的JavaWordCount是spark自带的例子($SPARK_HOME/examples/src/main/java/org/apache/spark/examples/JavaWordCount.java) 1.环境 OS:Red Hat Enterp

Default Method in Java 8

Default Methods The section Interfaces describes an example that involves manufacturers of computer-controlled cars who publish industry-standard interfaces that describe which methods can be invoked to operate their cars. What if those computer-cont

Java虚拟机一览表

免费和开源的 Java 虚拟机AegisVM (inactive since 2004).Apache Harmony — supports several architectures and systems. Discontinued November 2011. Apache License 2.0.Avian — A small, easily embeddable Java VM and classpath using just-in-time compilation.Azul Zulu

Java thread jargon

In Java thread topic, the task to be executed and the thread to drive the task are two concepts should be clarified. The working process is like the following: Create one task Create one thread to be attached on your created task. In Java, thread is

解决 Java 调用 Azure SDK 证书错误 javax.net.ssl.SSLHandshakeException

Azure 作为微软的公有云平台,提供了非常丰富的 SDK 和 API 让开发人员可以非常方便的调用的各项服务,目前除了自家的 .NET.Java.Python. nodeJS.Ruby,PHP 等语言都提供支持,详细的文档说明请参考: https://azure.microsoft.com/en-us/documentation/ 然而在使用过程中,以 Java 语言为例,在初始调用 Azure SDK/API 的时候大家会碰到类似下面的错误: [WARN] ServiceBusContrac