首先感谢czbk的老师,录制的视频,让我们有这么好的学习资料。……——

统计文件夹java文件的行数,首先想到的肯定是用递归的方法,因为文件夹下面可能包含文件夹,用递归的方法,代码容易写。(这和写简单的网络爬虫很像,一级页面下包含有二级页面的链接,二级页面又包含下一级的超链接)但是,用递归的方式有以下缺点:

  1. 如果文件夹层次很多,进而递归深度太大,容易栈溢出
  2. 用递归的方式,只能单线程执行,因为这一次的递归依赖于上一次的递归执行的结果

递归方式代码比较简单,如下:

public class LineCounterV1 {

    public static void main(String[] args) {
String path = "D:/wsc/eclipse/myeclipse-workspace/MyLineCount";
int count = getAllJavaFilesLineCount(new File(path));
System.out.println("总行数:" + count);
} /**
* 使用递归实现统计这个文件夹中(包含子孙文件夹中的)的所有.java文件的总行数
*
* @param dir
* 文件夹
* @return
*/
private static int getAllJavaFilesLineCount(File dir) {
int count = 0;
for (File file : dir.listFiles()) {
// 如果是.java文件,就统计行数
if (file.isFile() && file.getName().endsWith(".java")) {
count += FileUtils.getLineCount(file);
}
// 如果是文件夹,就递归调用
else if (file.isDirectory()) {
count += getAllJavaFilesLineCount(file);
}
}
return count;
}
}

其中,取得某个文件行数的代码如下:

public class FileUtils {

    /**
* 读取指定文件的内容,返回总行数
*
* @param file
* @return
*/
public static int getLineCount(File file) {
if (!file.isFile()) {
throw new IllegalArgumentException("请指定一个有效的文件对象!");
} try {
BufferedReader reader = new BufferedReader(new FileReader(file));
int count = 0;
while (reader.readLine() != null) {
count++;
}
reader.close();
return count;
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}

------------------------------------------------------------------------------------------------------------------------------------------

第二种方法,使用任务队列的方法,这是个很实用的技巧,特记录学习。

任务队列底层是一种队列的数据结构,可以存放在内存中,也可以保存在数据库中(递归的过程中使用的数据只能放在内存中),另外,很多个工作线程组成所谓的任务处理器,可以多线程处理任务队列中的任务(和一般的生产者消费者模型不同,这里任务队列中的线程既是任务的消费者,也是任务的生产者--其中消费者对应的是统计某个文件夹下所有文件的代码行数,生产者对应的是如果某个文件夹下保护子文件夹则创建新的任务并加入到任务队列尾)。

任务队列涉及到的类有以下:

  • 任务,这里指的是统计某个文件夹下的所有java文件的代码总行数
  • 任务队列,提供取出队头任务和加入队尾任务的功能,这里底层使用的是LinkedList来模拟
  • 处理线程,取出任务队列中的队头任务,并执行这个任务(按照面向对象原则,执行任务方法应该封装在任务类中而不是线程类中,因为只有任务类最清楚如何具体执行这个任务)
  • 一个测试类,初始化时往任务队列中放入一个任务(即统计根文件夹这个目录下的代码行数),开启任务处理线程,等待2秒钟(视具体情况),输出统计结果

使用任务队列的好处有:

  1. 可以处理大数据量
  2. 借助数据库持久化任务队列,可以实现高可靠性-因为不依赖于内存,可以应对断电等情况
  3. 多线程处理,在数据量比较大时,速度快

Task.java

public class Task {

    // 最终统计的总行数的结果
private static int count = 0; // 待统计的文件夹
private File dir; public Task(File dir) {
this.dir = dir;
} /**
* 办理任务:
*
* 遍历本文件夹中的所有子文件和字文件夹:<br>
* a, 如果是.java文件,就统计行数。<br>
* b, 如果是文件夹,就作为新的任务放到任务队列尾。
*
*/
public void execute() {
System.out.println(Thread.currentThread() + " ---> 正在办理任务:" + dir.getPath()); for (File file : dir.listFiles()) {
// 如果是.java文件,就统计行数
if (file.isFile() && file.getName().endsWith(".java")) {
synchronized (Task.class) { // 注意同步问题
count += FileUtils.getLineCount(file);
}
}
// 如果是文件夹,就作为新的任务放到任务队列尾
else if (file.isDirectory()) {
Task task = new Task(file);
TaskQueue.addToTail(task);
}
}
} /**
* 获取最终统计的总行数
*
* @return
*/
public static int getCount() {
return count;
} }

TaskQueue.java

public class TaskQueue {

    private static LinkedList<Task> queue = new LinkedList<Task>();

    /**
* 把任务放到队列的尾巴上
*
* @param task
* @return
*/
// 注意同步问题
public static synchronized void addToTail(Task task) {
queue.addLast(task);
} /**
* 从队列的头上取出一个任务,如果没有任务了,就返回null.
*/
// 注意同步问题
public static synchronized Task removeHead() {
if (queue.size() > 0) {
return queue.removeFirst();
} else {
return null;
}
} }

Worker.java

public class Worker extends Thread {

    /**
* 工作线程: 不断的从任务队列中取出一个任务并执行这个任务。
*/
public void run() {
System.out.println("==> 新的线程启动了:" + this); while (true) {
try {
// 如果有任务就办理
Task task = TaskQueue.removeHead();
if (task != null) {
task.execute();
}
// 如果没有任务,就休息一会再去看有没有任务
else {
Thread.sleep(2);
}
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
} }

测试类:

public class LineCounterV2 {

    public static void main(String[] args) throws Exception{
// 初始时只有一个任务(根目录)
String path = "D:/wsc/eclipse/myeclipse-workspace/MyLineCount";
Task task = new Task(new File(path));
TaskQueue.addToTail(task); // 开始多线程执行
int threadCount = 5;
for (int i = 0; i < threadCount; i++) {
new Worker().start();
} // 等待一会去看统计结果
Thread.sleep(2000);
int count = Task.getCount();
System.out.println("总行数:" + count); System.exit(0);
}
}

统计文件夹下java代码行数的小程序--主要是学习任务队列的思想的更多相关文章

  1. 使用python对文件夹里面所有代码行数进行统计。

    统计目录下所有的代码个数和总行数. # -*- coding: utf-8 -*- # @Author : ydf import json import os from pathlib import ...

  2. C++ 一个统计文件夹下所有代码文件行数的小工具

    // CodeLines.cpp : 定义控制台应用程序的入口点. // #include "stdafx.h" #include <Commdlg.h> #inclu ...

  3. java代码行数统计工具类

    package com.syl.demo.test; import java.io.*; /** * java代码行数统计工具类 * Created by 孙义朗 on 2017/11/17 0017 ...

  4. iOS 统计Xcode整个工程的代码行数

    小技巧5-iOS 统计Xcode整个工程的代码行数 1.打开终端 2.cd 空格 将工程的文件夹拖到终端上,回车,此时进入到工程的路径 此时已经进入到工程文件夹下 3.运行指令 a. find . - ...

  5. Linux 统计文件夹下文件个数及目录个数

    1. 统计文件夹下文件的个数 ls -l | grep "^-" | wc -l 2.统计文件夹下目录的个数 ls -l | grep "^d" | wc -l ...

  6. Linux上统计文件夹下文件个数以及目录个数

    对于linux终端用户而言,统计文件夹下文件的多少是经常要做的操作,于我而言,我会经常在谷歌搜索一个命令,“如何在linux统计文件夹的个数”,然后点击自己想要的答案,但是有时候不知道统计文件夹命令运 ...

  7. python (9)统计文件夹下的所有文件夹数目、统计文件夹下所有文件数目、遍历文件夹下的文件

    命令:os 用到的:os.walk   os.listdir 写的爬虫爬的数据,但是又不知道进行到哪了,于是就写了个脚本来统计文件的个数 #统计 /home/dir/ 下的文件夹个数 import o ...

  8. Linux统计文件夹下文件信息

    统计当前文件夹里面有多少文件,即统计文件个数 ls -l |grep "^-"|wc -l 统计当前文件夹里面有多少文件夹,即统计文件夹个数 ls -l |grep "^ ...

  9. linux 统计文件夹下文件,文件夹,所有个数

    统计某文件夹下文件的个数 ls -l |grep "^-"|wc -l 统计某文件夹下目录的个数 ls -l |grep "^d"|wc -l 统计文件夹下文件 ...

随机推荐

  1. DSP28377S - ADC学习编程笔记

    DSP28377S -  ADC学习编程笔记 彭会锋 2016-08-04  20:19:52 1 ADC类型导致的配置区别 F28377S的ADC类型是Type 4类型,我的理解是不同类型的ADC采 ...

  2. Java线程(一):线程安全与不安全

    作为一个Java Web开发人员,很少也不需要去处理线程,因为服务器已经帮我们处理好了.记得大一刚学Java的时候,老师带着我们做了一个局域网聊天室,用到了AWT.Socket.多线程.I/O,编写的 ...

  3. python中range和xrange的区别

    1.range生成一个列表:xrange生成一个生成器 2.用法都差不多  

  4. hduoj-----(2896)病毒侵袭(ac自动机)

    病毒侵袭 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submis ...

  5. javaWeb学习之运用myeclipse结合tomcat开发一些简单的jsp和service

    servlet是什么?     servlet是java服务器端编程.不同于我们之前写的一般的java应用程序,Servlet程序是运行在服务器上的,服务器有很多种.....现在只是用过 tomcat ...

  6. C#入门篇6-9:字符串操作 不值一提的函数【不看也行】

    // 判断输入的是否全是数字:返回结果:true:全是数字:false:有字幕出现 public static bool Isaccord1(string str) { bool bl = true; ...

  7. .NET开发知识体系

    记得几年前写过一篇关于.NET开发方面的知识总结,但是随着技术的发展以及自己技术理解的提升,觉得有必要对那篇文章加以更新和完善. 最近在园子里也看到有人写关于.NET知识体系的文章,特别是灵感之源写的 ...

  8. java.lang.ThreadGroup.enumerate

    java.lang.ThreadGroup.enumerate(Thread[] list) 方法复制该线程组及其子组中的所有活动线程到指定的数组. 声明 以下是java.lang.ThreadGro ...

  9. 小记:利用递归调用循环寻找MP3文件的方法。

    private void findMp3Data(File mp3file) { File[] filelist = mp3file.listFiles(); if (filelist != null ...

  10. js里面引入js

    document.write('<script src="http://js.xcar.com.cn/bbs/sidebar/js/publicSidebar.js"> ...