可以用readLine()方法,基本思路是每读一行,count up一下。
考虑你说的是净代码行数,那么就需要对每次读出的字符串进行检查,在做特定检查前最好将字符串trim()一下,防止前后空格带来的麻烦。
一般的检查很简单做,比如看该字符串的起始字符是不是合法字符(如//开头的就可以理解为注释,忽略,不用count up),等等
但是如果是多行注释,而且是用/* .....   */来标记的,那么就要采取特别的算法。比如如果读取了一行,发现是以/*开头的,那么你就要开始寻找下一个 */了。之间的这些行都不用count up。
还有其他很多情况都需要考虑,总之,像这样的东西难度不在实现上,而是在业务上,在需求分析上。因为你需要考虑的东西太多!而一旦需求确定,那么实现起来是很简单的。想象一下,如果你所要统计行数的文档格式是统一的,风格是统一的,那么你就很容易针对这些文档编写代码。但是这样的代码可重用性不好。
是一个矛盾的问题

解决方案 »

  1.   

    用readline()方法,读出来后trim()一下。。如果不是空行,就用startwith()方法判断开始的字符是不是注释,注意/* ……………… */这样注释要特殊处理。其他的就没有什么了。
      

  2.   

    java初学者,大家说的方法都在什么包下也说一下好吗
      

  3.   

    写出一部分,大家给点意见import java.io.*;public class count {
        public static void main(String args[]) {
            String s;
            FileReader file;
            BufferedReader in = null;
            int num1 = 0, num2 = 0,num3 = 0,num4, len = 0;
            try {
                File f = new File(args[0]);
                file = new FileReader(f);
                in = new BufferedReader(file);
            } catch (FileNotFoundException e) {
            } catch (IOException e) {
            }
            try {
                while ((s = in.readLine()) != null) {
                    num1++;
                    len = s.trim().length();
                    System.out.print(len+"\n");
                    if (len == 0)
                        num2++;
                    if(s.trim().startsWith("//"))
                        num3++;            }
            }catch (IOException exp) {
            }
            System.out.print(new StringBuffer().append(args[0]).append(":").append(num1).append(":").append(num1 - num2 - num3).toString());
        }
    }
      

  4.   

    package com.huawei.sw1.clog;import java.io.File;
    import java.io.FileReader;
    import java.io.LineNumberReader;
    import java.io.IOException;/**
     * @author zez
     * 
     * 源文件代码行统计工具Java版 :)
     */
    public class Clog { //多文件代码统计汇总结果
    private int gcommentLineNum = 0; private int gcodeAndCommentLinNum = 0; private int gblankLineNum = 0; private int gtotalLineNum = 0; private int gblankAndCommentLinNum = 0;


    //单个文件统计信息
    private LineNumberReader lReader; private int commentLineNum = 0; private int codeAndCommentLinNum = 0; private int blankLineNum = 0; private int totalLineNum = 0; private int blankAndCommentLinNum = 0;

    // private int logicLineNum = 0; //初始化
    private void init() {
    lReader = null;
    commentLineNum = 0;
    codeAndCommentLinNum = 0;
    blankLineNum = 0;
    totalLineNum = 0;
    blankAndCommentLinNum = 0;
    // logicLineNum = 0;
    } /**
     * 判断文件类型,并取得此文件
     * 
     * @param fileName
     * @return file, if not a source code file, return NULL .
     */
    private File getSourceFile(String fileName) {
    if (fileName == null || fileName.trim().length() == 0) {
    System.out.println("\nThe file name /* is null !\n");
    return null;
    }
    File file = new File(fileName);
    // 如果是目录,返回此目录
    if (file.isDirectory()) {
    return file;
    }
    //文件是否存在
    if (!file.exists()) {
    System.out.println("\nThe file " + fileName
    + " is don't exists !\n");
    return null;
    }

    /**
     * 判断是否是.c .cpp .java文件
     */
    if (fileName.indexOf('.') > 0) {
    String fileExt = fileName.substring(fileName.lastIndexOf('.') + 1).toLowerCase();
    if (!fileExt.equals("c") && !fileExt.equals("cpp") && !fileExt.equals("h")
    && !fileExt.equals("java")&& !fileExt.equals("hpp")) {

    System.out.println("\nThe file " + fileName
    + " is not a C or C++ or JAVA source file !\n");
    return null;

    }
    } //文件大小是否大于64k,不过大于64k仍可以计算
    if (file.length() > 65535) {
    System.out.println("\nThe file " + fileName
    + " is too large than 64k ,but It can work :)!\n");
    }
    //文件大小如果小于3个字节,返回空
    if (file.length() < 3) {
    System.out.println("\nThe file " + fileName
    + " has no content \n");
    return null;
    } return file;
    } /**
     * 打开文件
     * @param file 
     * @throws Exception
     */
    private void openFile(File file) throws Exception {
    try {
    lReader = new LineNumberReader(new FileReader(file));
    } catch (Exception e) {
    throw e;
    }
    } /***************************************************************************
     * 行数计算主函数 算法: 循环每次读取一行,分几种情况进行计算 1.空行 2.//开头 肯定为注释行 3.//在代码后面,
     * 按代码行算,并处理//在字符串中情况 4.以/*开头的情况,调用专门块注释计算方法 5./* 在代码后面情况,处理同上
     *  
     */ private void countLineNum() throws Exception { try {
    while (true) { //未到文件尾
    String str = lReader.readLine(); //取得一行代码

    totalLineNum++; //总行数加一

    if (str == null) { //判断是否为文件尾

    totalLineNum--;
    return;
    } else { //否则进行计算
    str = str.trim(); //去两头空格
    // countLogicLineNum(str);
    if (str.length() == 0) { //如果为空,则为空行,空行数加一
    blankLineNum++; } else if (str.startsWith("//")) { //如果是以//开头,为注释行,即使此行有//注释,但非开头,则要按代码行算
    commentLineNum++; } else if (str.indexOf("//") > 0 && isNotInStr(str, "//")) { // //在行中,并判断不是在字符串中
    codeAndCommentLinNum++;
    } else if (str.indexOf("/*") >= 0) {
    //如果/*在行中,判断是否是在""内 ,否则为注释行
    if (isNotInStr(str, "/*")) {
       countCommentLin(str);//计算/**/ 内的注释行数
    }
    }
    }
    }
    } catch (IOException e) {
    throw new Exception("文件读取时出错 !\n");
    }
    } /**
     * 块注释计算方法 判断是否块注释结束 否则读下一行 循环
     */
    private void countCommentLin(String str) throws Exception {
    try {
    commentLineNum++;
    //处理 /*some comment */ 即只一行的情况,并处理 /*/ 这种情况
                if((str.substring( str.indexOf( "/*")+2).indexOf( "*/")>=0)){
                 //是否有代码
    if(str.length() > str.indexOf( "*/")-str.indexOf( "/*")){
    codeAndCommentLinNum++;
       commentLineNum--;
       // countLogicLineNum(str);
    }
    //处理 /*xxx*/ some code /*  这种情况
    if(str.lastIndexOf( "*/")>str.lastIndexOf( "/*")+1)
    {
    // countLogicLineNum(str);
    return;
    }
    }
                //一般情况, some code /* some comment
                if(str.indexOf( "/*")>0){
    codeAndCommentLinNum++;
       commentLineNum--;
        }

           do {
    str = lReader.readLine(); //不是注释尾,取下一行代码
    totalLineNum++;
    //如果到文件尾,返回
    if (str == null) {
    totalLineNum--;
    return;
    }
    str = str.trim(); //去空格
    //是否到注释尾,如果后面还有代码,按混合行算
    if (str.indexOf("*/") >= 0) {
    commentLineNum++;
    if (str.length() > str.indexOf("*/") + 2) {
    codeAndCommentLinNum++;
    commentLineNum--;
    // countLogicLineNum(str);
    }
    return;
    } else {
    if (str.length() == 0) { //是空行
    blankLineNum++; //空行加一
    blankAndCommentLinNum++; //注释中空行加一
                        } else {
    commentLineNum++; //注释加一
    }
    }
    } while (true); } catch (IOException e) {
    throw new Exception("文件读取时出错 !\n");
    }
    }
      

  5.   


    /*
     * 判断 某字符 是否是字符串中,特别注释字符. 算法 : 字符串中是否有注释符号 如没有,返回 false 字符串中有 " 
     * ,如没有,返回true 注释符号在""之前,返回true;否则,继续 str = str的非\"的"后面部分 循环
     */
    private boolean isNotInStr(String str, String subStr) { while (str.indexOf(subStr) >= 0) {
    if (str.indexOf('"') >= 0) {
    if (str.indexOf('"') > str.indexOf(subStr)) {
    return true;
    } else {
    str = str.substring(str.indexOf('"') + 1); while (str.indexOf('\\') >= 0
    && str.indexOf('"') == str.indexOf('\\') + 1) {
    str = str.substring(str.indexOf('"') + 1);
    }
    str = str.substring(str.indexOf('"') + 1);
    }
    } else {
    return true;
    }
    }
    return false;
    }
    /**
     * 计算一行中的逻辑代码行
     * 基本法:计算代码行中的 ; 和 { 的个数
     * 缺陷: 现在无法对注释中的 ; 和 { 情况进行剔除 (//后面的注释和 块注释尾标志所在行的注释)
     * 有兴趣的话来完成吧:)
     * 做完了最好给我发一份过来 .OK
     * @param str
     */
    /* private void countLogicLineNum(String str)
    {
       String aStr = str;
       while(aStr.indexOf( ";")>0 && isNotInStr(aStr,";"))
       {
       logicLineNum++;
       aStr = aStr.substring( aStr.indexOf( ";")+1);
       }
       aStr = str;
       while(aStr.indexOf( "{")>=0)
       {
       logicLineNum++;
       aStr = aStr.substring( aStr.indexOf( "{")+1);
       }
      
    }**/
    /**
     * 打印计算结果
     *
     */
    private void printResult() {

    int codeLineNum = totalLineNum - blankLineNum - commentLineNum;
    System.out.println("总行数为      : " + totalLineNum);
    System.out.println("代码行数为    : " + codeLineNum);
    System.out.println("总注释行数为  : "
    + (commentLineNum + codeAndCommentLinNum));
    System.out.println("空行数为      : " + blankLineNum);
    System.out.println("混合行数为    : " + codeAndCommentLinNum);
    System.out.println("纯注释行数为  : " + commentLineNum);
    System.out.println("注释中空行数为: " + blankAndCommentLinNum);
    // System.out.println("逻辑代码行数为 : " + logicLineNum);
    int commentRat ;
    if((commentLineNum + codeAndCommentLinNum)==0 || totalLineNum==0 )
    {
    commentRat = 0;
    }else{
    commentRat = (100 * (commentLineNum + codeAndCommentLinNum) / totalLineNum);
    }
    System.out.println("注释率为     : "
    + commentRat
    + "%");
    }

    /**
     * 打印计算结果
     *
     */
    private void printTotalResult() {

    int gcodeLineNum = gtotalLineNum - gblankLineNum - gcommentLineNum;
    System.out.println("总行数为      : " + gtotalLineNum);
    System.out.println("代码行数为    : " + gcodeLineNum);
    System.out.println("总注释行数为  : "
    + (gcommentLineNum + gcodeAndCommentLinNum));
    System.out.println("空行数为      : " + gblankLineNum);
    System.out.println("混合行数为    : " + gcodeAndCommentLinNum);
    System.out.println("纯注释行数为  : " + gcommentLineNum);
    System.out.println("注释中空行数为: " + gblankAndCommentLinNum);
    // System.out.println("逻辑代码行数为 : " + logicLineNum);
    int commentRat ;
    if((gcommentLineNum + gcodeAndCommentLinNum)==0 || gtotalLineNum==0 )
    {
    commentRat = 0;
    }else{
    commentRat = (100 * (gcommentLineNum + gcodeAndCommentLinNum) / gtotalLineNum);
    }
    System.out.println("注释率为     : " + commentRat+ "%");
    }
    /**
     * 统计结果汇总
     *
     */
    private void countTotalNum(){
    gcommentLineNum += commentLineNum ;
    gcodeAndCommentLinNum += codeAndCommentLinNum;
    gblankLineNum += blankLineNum;
    gtotalLineNum += totalLineNum;
    gblankAndCommentLinNum += blankAndCommentLinNum;
    }
    /**
     * 嵌套计算文件夹内所有文件
     * @param fileName //文件或目录名
     * @throws Exception
     */
    private void count(String fileName) throws Exception {
    try {
    File file = getSourceFile(fileName);
    if (null != file) {
    if (file.isFile()) {
    System.out.println("\n源文件: " + fileName + " 统计信息为: ");
    init();
    openFile(file);
    countLineNum();
    printResult();
    countTotalNum();
    } else if (file.isDirectory()) {
    String[] fNameList = file.list();
    for (int i = 0; i < fNameList.length; i++) {
    count(fileName + "\\" + fNameList[i]);
    }
        }
    }
    } catch (Exception e) {
    throw e;
    }
    } public static void main(String[] args) {
    try {
    String fileName;
    if (args == null || args.length == 0) {
    System.out.println("请输入要统计的文件或目录:\n");
    byte[] buff = new byte[255];
    System.in.read(buff);
    fileName = new String(buff).trim();

    } else {
    fileName = args[0];
    }
    //  fileName = "c:\\test"; Clog clog = new Clog();
    long begin = System.currentTimeMillis() ;
    clog.count(fileName);
    if(new File(fileName).isDirectory() ){
       System.out.println("目录 "+fileName+" 下所有源文件统计汇总如下:\n") ;
       clog.printTotalResult() ;
    }
    long end = System.currentTimeMillis() ;
        System.out.println("\n 用时: "+(end-begin)+" 毫秒 .") ;
    } catch (Exception e) {
                if(null==e.getMessage() || e.getMessage().trim() .length() ==0){
                 System.out.println(" 系统出错,错误信息为 :\n") ;
                 e.printStackTrace() ;
                }else{
                 System.out.println(" 程序出错,错误信息为 :\n   " + e.getMessage());
                }
    }
    }
    }
      

  6.   

    花了一天的时间...
    欢迎测试提bug...
    建议和商业源码统计工具对比,然后自己数数,看哪个对 :)
      

  7.   

    /**
     * 计算一行中的逻辑代码行
     * 基本法:计算代码行中的 ; 和 { 的个数
     * 缺陷: 现在无法对注释中的 ; 和 { 情况进行剔除 (//后面的注释和 块注释尾标志所在行的注释)
     * 有兴趣的话来完成吧:)
     * 做完了最好给我发一份过来 .OK
     * @param str
     */
    请教什么是逻辑代码行?
      

  8.   

    这个地方的注释看不太明白,代码也很难懂,能不能写清楚一点?
    急用啊!谢谢
    /*
     * 判断 某字符 是否是字符串中,特别注释字符. 算法 : 字符串中是否有注释符号 如没有,返回 false 字符串中有 " 
     * ,如没有,返回true 注释符号在""之前,返回true;否则,继续 str = str的非\"的"后面部分 循环
     */
    private boolean isNotInStr(String str, String subStr) {while (str.indexOf(subStr) >= 0) {
    if (str.indexOf('"') >= 0) {
    if (str.indexOf('"') > str.indexOf(subStr)) {
    return true;
    } else {
    str = str.substring(str.indexOf('"') + 1);while (str.indexOf('\\') >= 0
    && str.indexOf('"') == str.indexOf('\\') + 1) {
    str = str.substring(str.indexOf('"') + 1);
    }
    str = str.substring(str.indexOf('"') + 1);
    }
    } else {
    return true;
    }
    }
    return false;
    }