GitHub项目地址:https://github.com/SimonQida/QWordCount

PSP表格:

 

      

 

解题思路:

  因为在之前学习过的oop课程中,了解过了一些java,所以在做项目的时候查阅的java相关知识就不一一列出。

  其实这个小项目要实现的东西相比于词法分析器并不是很难,与之不同的是,要辨别输入的参数和文件操作之类的东西,项目打包等比较细小的东西。

  主要还是查了一下怎么将.java文件打包成一个jar包,然后将jar包打包成一个.exe(配置环境..)    

  以及jdk和jre的联系区别,命令行中编译.java时用到的java指令和javac指令的具体使用,同时也了解了java项目文件组织形式   

程序设计实现过程

  在做这个小项目的时候,建了两个类,一个可以保存输入文件的信息,一个可以保存向目标文件输出哪几个文件的信息。  

  保存文件信息的doc类

class doc {
    String name;
    String text;
    int linecount =1,wordcount = 0,symbolcount=0,codeline=0,nullline = 0,balaline =666;
    boolean[] temp ={};
    public doc(){}
    public doc(String n,String t,boolean[] para){
        name = n;
        text = t;
        temp = para;
        cal();
    }
    public String  mes(){
        String message= "name:"+name+"\n";
        if(temp[2] ==true)
            message +="\tsymbolcount:"+symbolcount;
        
        if(temp[1] == true)
            message +="\twordcount:"+wordcount;
        
        if(temp[0]==true)
            message +="\tlinecount:"+linecount;
        if(temp[3] == true)
            message +="\tcodeline:"+codeline+"\tnullline:"+nullline+"\tbalaline:"+balaline;
        return message;
    }
    public static boolean isChinese(char c) {  
        return c >= 0x4E00 &&  c <= 0x9FA5;// 根据字节码判断  
    }      
    public static boolean isword(char c) {  
        return (c>='A'&&c<='Z')||(c>='a'&&c<='z')||(c>='0'&&c<='9');  
    }  
    public static boolean isnum(char c) {  
        return (c>='0'&&c<='9');  
    }
    public static boolean issymbol(char c){
        return !(isChinese(c)||isword(c));
    }
    private void cal()

 

  保存文件链的类

 

class outdoc {
    String name;
    ArrayList children =new ArrayList();
    public void clear(){
        children.clear();
    }
}

  

  接受参数等一系列的判断具体化就不说了,值得一提的是,我终于知道在我的程序里各种抛出异常了。

                if(args[i].length()!=2)
                    throw new Exception("a para after a -");
                if(args[i].charAt(1)=='o'){    //参数是-o
                    isout= true;
                    if(i-1<0)                //first param can't be -o
                        throw new Exception("-o as the first para");
                    if(i+1>=args.length)
                        throw new Exception("-o as the last para");
                    if(args[i+1].charAt(0)=='-'||args[i-1].charAt(0)=='-')//the para before 
                                                            // or after must be filename
                        throw new Exception("no filename after||before -o");
                    if(docarr.size()==0)                //has to have at least one filename message
                        throw new Exception("no file message to write!");

 

  有一些文件操作函数,有一个二次重载的用来遍历当前文件夹的TraversalDir函数,返回符合条件的文件名

  在第二个Traversal()函数中,使用了文件过滤器

public static String[]  TraversalDir(){
        File file = new File(".");
        /*try {
            System.out.println(file.getCanonicalPath());
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }*/
        String[] fileList = file.list();        //get the filename in the dir
        ArrayList<String> returnlist =new ArrayList<String>();
        File[] fs = file.listFiles();
        for(int i =0;i<fileList.length;++i){
                        //create the file handle in the dir by typing in one's name
            if(fs[i].isFile()){
                returnlist.add(fileList[i]);
                //System.out.println(fileList[i]);
            }
        }
        return (String[])returnlist.toArray(new String[0]);
    }
    public static String[]  TraversalDir(String suffix){
        File file = new File(".");
        try {
            System.out.println(file.getCanonicalPath());
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        MyFilter filter = new MyFilter(suffix);
        String[] fileList = file.list(filter);        //get the filename in the dir
        ArrayList<String> returnlist =new ArrayList<String>();
        File[] fs = file.listFiles(filter);
        for(int i =0;i<fileList.length;++i){
                        //create the file handle in the dir by typing in one's name
            if(fs[i].isFile()){
                returnlist.add(fileList[i]);
                System.out.println(fileList[i]);
            }
            
        }
        return (String[])returnlist.toArray(new String[0]);
    }

下面这几个函数就是基本的文件操作函数,具体就不说了

    public static boolean createFile(String filePath){
        boolean result = false;
        File file = new File(filePath);
        if(!file.exists()){
            try{
                result = file.createNewFile();
            }
            catch(IOException e){
                e.printStackTrace();
            }
        }
        else System.out.println("file exists");
        return result;
    }
    public static String readFileByChars(String filePath){
        File file = new File(filePath);
        if(!file.exists()||!file.isFile()){
            return null;
        }
        StringBuffer content = new StringBuffer();
        try{
            char[] temp = new char[1];                //这tm成了逐个字符读入了
            InputStream fileInputStream = new FileInputStream(file);
            InputStreamReader inputStreamReader = new InputStreamReader(fileInputStream, "UTF-8");  
            while(inputStreamReader.read(temp)!=-1){
                content.append(new String(temp));
                temp = new char[1];
            }
            fileInputStream.close();
            inputStreamReader.close();
        }catch (FileNotFoundException e){
            e.printStackTrace();
        }catch (IOException e){
            e.printStackTrace();
        }
        return content.toString();
    }
    public static void writeFileByChars(File file,String mes) throws IOException{
        BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter(file)); 
        bufferedWriter.write(mes);
        bufferedWriter.flush();// 清空缓冲区  
        bufferedWriter.close();// 关闭输出流  
    }

 

  测试设计过程

  语句覆盖就是要保证设计的测试用例应至少覆盖函数中所有的可执行语句”,为此,我针对WordCount类中的count方法,使用语句覆盖指标设计测试用例,共产生10个测试用例。 

  白盒测试:

  根据软件产品的内部工作过程,在计算机上进行测试,以证实每种内部操作是否符合设计规格要求,所有内部成分是否已经过检查。这种测试方法就是白盒测试。白盒测试把测试对象看做一个打开的盒子,允许测试人员利用程序内部的逻辑结构及有关信息,设计或选择测试用例,对程序所有逻辑路径进行测试。通过在不同点检查程序的状态,确定实际的状态是否与预期的状态一致。

  白盒测试程序片段:

private static void testmain(String[] onefile) {
        // TODO Auto-generated method stub
        try {
            newlei.main(onefile);
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

  等价类划分:

  把所有可能的输入数据,即程序的输入域划分成若干部分(子集),然后从每一个子集中选取少数具有代表性的数据作为测试用例。该方法是一种重要的,常用的黑盒测试用例设计方法。在子集合中,各个输入数据对于揭露程序中的错误都是等效的,并合理地假定:测试某等价类的代表值就等于对这一类其它值的测试,因此,可以把全部输入数据合理划分为若干等价类,在每一个等价类中取一个数据作为测试的输入条件就可以用少量代表性的测试数据取得较好的测试结果。

  测试用例:  

        String[] onefile = {"javaforcednote"};
        String[] cwlonefile = {"-c","javaforcednote"};
        String[] files = {"*"};
        String[] suffixfiles = {"*.c"};
        String[] afile = {"-a","javaforcednote"};
        String[] ofile = {"javaforcednote","-o","output.txt"};
        String[] cwlfiles = {"-c","-w","-l","*"};
        String[] stoplistfile = {"javaforcednote","-e","stoplist"};
        String[] allparafiles = {"-c","-w","javaforcednote","-o","output.txt","-e","stoplist","-c","*.c","-o","output.tt"};
        String[] out_of_order = {"-c","-a","javaforcednote","-e","stoplist","-o","output.tt","*.c"};    

  其中我对大部分可能的 参数 文件 输出文件的顺序多少和相对位置关系,都给予考虑。设计出了符合正常使用思路的10个测试用例:

    * 单一文件

    * 对某个参数单一文件

    * 当前目录下的全部文件

    * 后缀文件

    * 输出各种行数的单一文件

    * 指定输出文件的单一文件

    * 取三个参数的全部文件

    * 指定禁用词表的单一文件

    * 大杂烩

    * 逻辑正确的乱序

  当然你也可以将不同的文件信息输出到不同的文件中,也可以随意改变-e filename的位置,只要保证-e后紧跟停用词表名(自定义)。

 

  程序逻辑不可能包含全部的可能,欢迎拍砖

  参考文献


    http://www.cnblogs.com/Jackc/archive/2009/09/16/1567203.

    http://blog.csdn.net/sunkun2013/article/details/13167099

    http://blog.csdn.net/vincetest/article/details/

    https://zh.wikipedia.org/wiki/

    https://zh.wikipedia.org/wiki/