JAVA递归思想实现全盘搜索文件系统之进阶版

JAVA递归思想实现全盘搜索文件系统之进阶版

转载自:https://tufeng.xyz/java/26.html(来源于:兔峰博客)

上一篇我们通过文章 JAVA递归思想实现全盘检索文件系统之基础版 了解到了全盘检索搜索文件系统所用到的核心思想——递归思想,

这一片文章所要讲解的实例将在上一篇基础上进行改进,主要借助多线程提升检索搜索文件系统的速度。

上一篇文章检索搜索文件系统的大体流程就是,先搜C盘,再搜D盘,再搜E盘。。。。我们可以看到,这样一个盘一个盘的搜下去,还是太慢了,

那么有没有办法多个盘符一起搜索呢,这样就能大大缩短检索文件的时间? 答案是可以的,这里我们主要借助多线程思想,为保证线程安全,

这里还将用到线程锁,小伙伴们还可以学习或者巩固一下关于线程方面的知识。

解析:

这里工具类相比上次多了一些全局变量,关于他们代表的含义请看下面实例代码中旁边的注释。

下面我来讲解一下globleSearchFile()函数关键部分:

这里遍历文件系统盘符,为每一个盘符开一个线程,线程里面调用searchFile()函数执行文件搜索,

多个线程同时运行,多个盘符同时进行搜索,效率大大提高

线程里面searchFile()函数执行完毕后对结果进行判断:

  1. 如果find为true,则表示找到目标文件,调用findFile()函数,将全局变量find赋值true,

    由于所有线程里面在执行searchFile()函数时,开头都会做如下判断

     if(find) {return false;}
    

这表示如果找到目标文件,则立即返回,不再查找

所以此时(找到目标文件)所有线程停止查找,立即执行结束

这样做的好处就是避免不必要的系统资源的消耗

  1. 如果find为false,则表示搜索完整个盘符后仍然没有找到目标文件,然后调用notFile()函数

    search_num变量加一,当搜索完毕的盘数的数量达到最大值,即表示全盘搜索完毕,如下:

     if(search_num==disk_num) {   // 全盘搜索完毕,激活锁
     	    	  synchronized (object) {
     					 over = true;						
     					 object.notify();
     					
     				}
     	      } // if search_num==disk_num
    

此时激活锁,返回全盘搜索结果,全盘搜索完毕。

实例代码如下,可以测试一下:

package m1;

import java.io.File;

public class Test {
	 
     String find_path = null;       // 目标文件所在的路径(如果有的话)
	
	Object object = new Object();   // 线程锁
	volatile boolean find = false;   // 目标文件是否找到
	boolean over = false;            //整个文件系统是否检索搜索完毕
	
	Object object2 = new Object();   // 线程锁
	int disk_num = 0;                // 盘符数量
	int search_num = 0;              // 已搜索完毕的盘符数量
	
		public void find_file() {    // 找到文件后调用该函数,激活锁
			
            synchronized (object) {
				 
				 over = true;
				 find = true;
				 object.notify();      
//				 System.out.println("find path="+dir_path);
				
			}
		}
		public void not_findFile() {    //搜索完盘符后没有找到目标文件,调用该函数
			
			 synchronized (object2) {			     
				 search_num++;
			      if(search_num==disk_num) {   // 全盘搜索完毕,激活锁
			    	  synchronized (object) {
							 over = true;						
							 object.notify();
							
						}
			      } // if search_num==disk_num
			}
		}
		// 搜索文件核心函数(递归函数)
		public  boolean searchFile(String dir_path,String des_fileName) {
				
			 if(find) {return false;}
			 
			 File dir_file = new File(dir_path);
			 File[] files = dir_file.listFiles();
			 
//			 if(dir_file.isFile()&&dir_file.getName().equals(des_fileName)) {find_file(dir_file.getAbsolutePath());}
			  if(files!=null) {
				 for(File file:files) {
					 
					 if(file.isDirectory()) {
		                boolean exist =  searchFile(file.getAbsolutePath(),des_fileName);
		                 if(exist) {return true;}
		                 else {continue;}
					 }
					 else {
					//	 System.out.println("file: "+file.getAbsolutePath());
					//	 if(file.getName().equals(des_fileName)) {return true;}
						 
						 String file_name = file.getName();
						 
						 if(file_name.equals(des_fileName)) { 
							 find_path = file.getAbsolutePath();
							 return true;
						 }

					}  // if is file
				 }    // for
			 }
			  
			return false;
		 }  //  list_files
	
	//全盘搜索文件系统入口函数
  public String globleSearchFile(String des_fileName) {
		  File[] roots = File.listRoots();
		  
		  for(File file:roots) {
			  
			  			 new Thread(new Runnable() {
			  		// 遍历盘符,为每一个盘符开启一个线程,开始搜索目标函数		
			  				@Override
			  				public void run() {
			  					boolean find = searchFile(file.getAbsolutePath(), des_fileName);
			  					   if(find) {find_file();}   //盘符搜索完毕后,对搜索结果进行判断处理
			  					   else {not_findFile();}
			  				}
			  			}).start();
			    	   
			      } // for		  
		  
		  synchronized (object) {   //线程锁,如果搜索完毕,则释放锁,结束全盘搜索,返回搜索结果
			  while(!over) {
				  try {
					object.wait();
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			  }
		}
		  
//		  System.out.println("find? "+find);

		  return find_path;
		 
	 }
	 
	 public static void main(String[] args) {
		
		 long start_time = System.currentTimeMillis();
		 
		 System.out.println("start find...");
		 Test searchFile = new Test();
		 String path = searchFile.globleSearchFile("wslk_strings.xml");
		 
		 if(path!=null) {System.out.println("already find, file path :"+path);}
		 else {System.out.println("sorry,not find the file");}
		 
		 System.out.println("用时:"+((System.currentTimeMillis()-start_time))+"毫秒");
//		 new SearchFile().new SearchThread("G:\\", "ToolTip.html").start();
		 
	}
}
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
前天正好要找一个本地文件, 就用java实现了, 全盘的本地文件搜索功能. 代码不依赖其它第三方jar, 连日志都用system.out了. 初学者可以了解下. 主程序: LocalFileSearcher.java LocalFileSearcher searcher = new LocalFileSearcher(); searcher.doSearch("迅雷"); log如下: Start search keyword: 迅雷 Start search all drivers! success: E:\迅雷下载 success: F:\迅雷下载 success: C:\Users\Administrator\Desktop\迅雷.lnk success: C:\ProgramData\Microsoft\Windows\Start Menu\Programs\迅雷软件 success: C:\ProgramData\Microsoft\Windows\Start Menu\Programs\迅雷软件\迅雷 success: C:\Users\All Users\Microsoft\Windows\Start Menu\Programs\迅雷软件 success: C:\Users\Administrator\AppData\Roaming\Microsoft\Internet Explorer\Quick Launch\迅雷.lnk success: C:\Users\Administrator\AppData\Roaming\Microsoft\Windows\Libraries\迅雷下载.library-ms success: C:\ProgramData\Microsoft\Windows\Start Menu\Programs\迅雷软件\迅雷\迅雷影音.lnk success: C:\Users\All Users\Microsoft\Windows\Start Menu\Programs\迅雷软件\迅雷 success: C:\Users\Administrator\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\迅雷软件 success: C:\Users\All Users\Microsoft\Windows\Start Menu\Programs\迅雷软件\迅雷\迅雷影音.lnk success: C:\Users\Administrator\AppData\Roaming\Microsoft\Internet Explorer\Quick Launch\User Pinned\StartMenu\迅雷.lnk success: C:\Users\Administrator\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\迅雷软件\迅雷 success: C:\Users\Administrator\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\迅雷软件\迅雷\卸载迅雷.lnk success: C:\Users\Administrator\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\迅雷软件\迅雷\迅雷.lnk Search costs : 3861(ms) File searched : 154848 Folder searched: 31463 Success match : 16 后续再更新完善
递归算法实现二分查找的Java代码可以参考以下示例: ```java public class BinarySearch { public static void main(String[] args) { int[] nums = {1, 2, 6, 15, 18, 20, 25, 27, 35, 40, 45, 56, 62, 78, 88}; int findValue = 35; int binaryResult = binarySearch(nums, 0, nums.length - 1, findValue); System.out.println("元素第一次出现的位置(从0开始):" + binaryResult); } private static int binarySearch(int[] nums, int start, int end, int findValue) { if (start <= end) { int middle = (start + end) / 2; if (findValue == nums[middle]) { return middle; // 查找值等于中间值直接返回 } else if (findValue < nums[middle]) { return binarySearch(nums, start, middle - 1, findValue); // 小于中间值,在中间值之前的数据中查找 } else { return binarySearch(nums, middle + 1, end, findValue); // 大于中间值,在中间值之后的数据中查找 } } return -1; } } ``` 这个递归实现的二分查找算法首先检查开始下标`start`是否小于等于结束下标`end`,如果是,则计算中间下标`middle`。然后通过比较查找值`findValue`与中间值`nums[middle]`的大小,决定是在中间值之前的数据中查找还是在中间值之后的数据中查找,递归调用`binarySearch`方法。如果查找值等于中间值,则直接返回中间下标;如果查找值小于中间值,则在中间值之前的数据中查找,更新结束下标`end`为`middle - 1`;如果查找值大于中间值,则在中间值之后的数据中查找,更新开始下标`start`为`middle + 1`。如果开始下标大于结束下标,表示未找到查找值,返回-1。 这样的递归实现方式能够不断缩小查找范围,提高查找效率。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [二分查找递归解法(java)](https://blog.csdn.net/weixin_51577444/article/details/123763009)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* *3* [Java常用算法-二分查找算法(两种方法实现)](https://blog.csdn.net/zengqing2010/article/details/120680127)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值