文件夹目录下文件太多,list直接卡住的解决方式

1、系统最近遇到的一个问题,需要处理原始目录下的文件,而file.list() 方法相当于linux命令中的ls。当文件夹中的文件过多的时候,会直接卡死。卡死的主要原因是:

默认情况下,ls命令会将输出排序。为了排序,ls命令先将所有文件的名称读入内存。当遇到一个非常大的目录时,它就在那里不断地读入文件名,并且内存占用越来越大,直到将所有文件一次性以字母数字顺序列出来。

 

ls-1 -f命令并不执行排序操作,只是读取目录然后立即显示文件。


所以系统上获取文件进行了改造。java中直接执行linux命令可以使用Runtime.getRuntime().exec。但process.waitFor()方法可能发生无休止或者接近于无休止的阻塞。

造成 process.waitFor()的主要原因是,Process 需要向主线程汇报运行状况,缓存区是有限的。一直不清除缓存将导致阻塞。

方法一:需要在发送线程中开两个子线程:分别清空 InputStream 和 ErrorStream。

方法二:将process.waitFor()放在一个子线程中。在主线程中通过子线程的join方法设置超时时间。如果超过设置的时间,

process.waitFor仍然返回空,就将子线程打断,并将process.destroy();


系统最终采用第二种方法:

	private String[] listPathNew(int count) {
		 InputStreamReader ir = null;
		String[] readFile = new String[0];
		String line;  
	    List  files = new ArrayList();

		try {
			log.info("------开始从原始目录搬运文件");
			long startTime = System.currentTimeMillis();
			// 调用系统命令解压文件
			String [] cmd={"/bin/sh","-c","ls -l -f|head -"+count};
					
			File ofile = new File(ProComMailMutiply.oldmailbox_path);
			Process process = Runtime.getRuntime().exec(cmd, null, ofile);
			
			new ProcessClearStream(process.getInputStream(),"INFO",files).start();
	        new ProcessClearStream(process.getErrorStream(),"ERROR",files).start();
	           
			// 等待进程正常完成
			process.waitFor();

			readFile = (String[]) files.toArray(new String[files.size()]);
			
			log.info("------搬运文件花费了" + (System.currentTimeMillis() - startTime)
					+ " ms");
			
		} catch (Exception e) {
			log.error("搬运文件出错了" + e.toString());
		}finally{
			return readFile;
		}
	}
   
	
	public class ProcessClearStream extends Thread {
		private InputStream inputStream;
		private String type;
		private List files;
		
		ProcessClearStream(InputStream inputStream, String type, List files) {
		this.inputStream = inputStream;
		this.type = type;
		this.files = files;
		}

		public void run() {
			InputStreamReader inputStreamReader = new InputStreamReader(
					inputStream);
			BufferedReader br = new BufferedReader(inputStreamReader);
			try {
				// 打印信息

				String line = null;
			
				while ((line = br.readLine()) != null) {
					if(type.equals("INFO")){
					log.info("随机获取文件夹下的文件"+line);
			        File tempf = new File(ProComMailMutiply.oldmailbox_path+File.separator+line);
			        if(tempf.isFile())
					{
			        	files.add(line);
					} else{
						log.info(tempf+"不是文件");
					}      
				}else{
					log.error("打印错误输出流 :"+line);
					}
				}
			
			} catch (IOException ioe) {
				log.error("搬运文件出错了"+ioe.getMessage());
			}finally {		
				try {
					br.close();
				} catch (IOException e) {
					log.error("关闭文件流异常");
				}
			}
		}
	}




参与评论 您还未登录,请先 登录 后发表或查看评论

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

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
©️2022 CSDN 皮肤主题:大白 设计师:CSDN官方博客 返回首页

打赏作者

ankora

你的鼓励将是我创作的最大动力

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值