zoukankan      html  css  js  c++  java
  • 小米开源文件管理器MiCodeFileExplorer-源码研究(4)-文件操作工具类FileOperationHelper

    文件操作是非常通用的,注释都写在源代码中了,不多说~
    需要特别说明的是,任务的异步执行和IOperationProgressListener。
    拷贝和删除等操作,是比较费时的,采用了异步执行的方式~


    Android异步执行,我也是初次了解,在CSDN上找了一篇文章,后续写个单独的例子,单独写1篇介绍。
    http://blog.csdn.net/xufenghappy6/article/details/7343899
    异步执行+事件通知 是一种比较流行的模式,比同步等待很多时候要好。


    另外,特别需要说明的是,Java应用程序中、Android、Windows开发、Linux Shell都会有文件File的概念,他们本质是一样的。
    文件的核心概念基本一致,都是用的操作系统的文件概念,不同操作系统之间的区别也不大。
    创建、删除、重命名、复制、粘贴,输入-执行-输出,也都一样。


    package net.micode.fileexplorer.util;
    
    
    import java.io.File;
    import java.io.FilenameFilter;
    import java.util.ArrayList;
    
    
    import net.micode.fileexplorer.model.FileInfo;
    import android.os.AsyncTask;
    import android.os.Environment;
    import android.text.TextUtils;
    import android.util.Log;
    /**文件操作工具类,执行文件的创建、移动、粘贴、重命名、删除等*/
    public class FileOperationHelper {
    	private static final String LOG_TAG = "FileOperation";
        //内部文件集合,用来临时保存复制、移动等操作,用户选择的文件集合
    	private ArrayList<FileInfo> mCurFileNameList = new ArrayList<FileInfo>();
    
    
    	private boolean mMoving;
    
    
    	private IOperationProgressListener mOperationListener;
    
    
    	private FilenameFilter mFilter;
    
    
    	public interface IOperationProgressListener {
    		void onFinish();
    
    
    		void onFileChanged(String path);
    	}
    
    
    	public FileOperationHelper(IOperationProgressListener l) {
    		mOperationListener = l;
    	}
    
    
    	public void setFilenameFilter(FilenameFilter f) {
    		mFilter = f;
    	}
    
    
    	//根据路径和文件名,创建文件
    	public boolean CreateFolder(String path, String name) {
    		Log.v(LOG_TAG, "CreateFolder >>> " + path + "," + name);
    
    
    		File f = new File(Util.makePath(path, name));
    		if (f.exists())
    			return false;
    
    
    		return f.mkdir();
    	}
    
    
    	//拷贝若干个文件,把文件集合拷贝到“当前文件集合中mCurFileNameList”,可以供“粘贴操作”使用
    	public void Copy(ArrayList<FileInfo> files) {
    		copyFileList(files);
    	}
    
    
    	//粘贴,把当前文件集合中“mCurFileNameList”的文件,拷贝到目标路径下
    	public boolean Paste(String path) {
    		if (mCurFileNameList.size() == 0)
    			return false;
    
    
    		final String _path = path;
    		//异步执行某个任务
    		asnycExecute(new Runnable() {
    			@Override
    			public void run() {
    				for (FileInfo f : mCurFileNameList) {
    					CopyFile(f, _path);
    				}
    				//通知操作变化
    				mOperationListener.onFileChanged(Environment
    						.getExternalStorageDirectory().getAbsolutePath());
                    //粘贴之后,需要清空mCurFileNameList
    				clear();
    			}
    		});
    
    
    		return true;
    	}
    
    
    	//是否可以“粘贴”,mCurFileNameList有元素
    	public boolean canPaste() {
    		return mCurFileNameList.size() != 0;
    	}
    
    
    	//开始移动,标记“正在移动”,拷贝文件集合
    	public void StartMove(ArrayList<FileInfo> files) {
    		if (mMoving)
    			return;
    
    
    		mMoving = true;
    		copyFileList(files);
    	}
    
    
    	//移动状态
    	public boolean isMoveState() {
    		return mMoving;
    	}
    
    
    	//能否移动,假设path为“C:/a/b”,f.filePath为“C:、/a/b/c/d.png”,不能移动
    	//TODO 感觉不太靠谱啊,为啥不能移动到文件的上级目录呢?
    	public boolean canMove(String path) {
    		for (FileInfo f : mCurFileNameList) {
    			if (!f.IsDir)
    				continue;
    
    
    			if (Util.containsPath(f.filePath, path))
    				return false;
    		}
    
    
    		return true;
    	}
    
    
    	//清空当前文件集合
    	public void clear() {
    		synchronized (mCurFileNameList) {
    			mCurFileNameList.clear();
    		}
    	}
    
    
    	//停止移动,移动文件是异步执行,结束后有事件通知
    	public boolean EndMove(String path) {
    		if (!mMoving)
    			return false;
    		mMoving = false;
    
    
    		if (TextUtils.isEmpty(path))
    			return false;
    
    
    		final String _path = path;
    		asnycExecute(new Runnable() {
    			@Override
    			public void run() {
    				for (FileInfo f : mCurFileNameList) {
    					MoveFile(f, _path);
    				}
    
    
    				mOperationListener.onFileChanged(Environment
    						.getExternalStorageDirectory().getAbsolutePath());
    
    
    				clear();
    			}
    		});
    
    
    		return true;
    	}
    
    
    	public ArrayList<FileInfo> getFileList() {
    		return mCurFileNameList;
    	}
    
    
    	//异步执行某个任务
    	//android的类AsyncTask对线程间通讯进行了包装,提供了简易的编程方式来使后台线程和UI线程进行通讯:后台线程执行异步任务,并把操作结果通知UI线程。
    	//可以参考http://blog.csdn.net/xufenghappy6/article/details/7343899
    	private void asnycExecute(Runnable r) {
    		final Runnable _r = r;
    		new AsyncTask() {
    			@Override
    			protected Object doInBackground(Object... params) {
    				synchronized (mCurFileNameList) {
    					_r.run();
    				}
    				if (mOperationListener != null) {
    					mOperationListener.onFinish();
    				}
    
    
    				return null;
    			}
    		}.execute();
    	}
    
    
    	//某个路径是否被选中
    	public boolean isFileSelected(String path) {
    		synchronized (mCurFileNameList) {
    			for (FileInfo f : mCurFileNameList) {
    				if (f.filePath.equalsIgnoreCase(path))
    					return true;
    			}
    		}
    		return false;
    	}
    
    
    	//文件重命名
    	public boolean Rename(FileInfo f, String newName) {
    		if (f == null || newName == null) {
    			Log.e(LOG_TAG, "Rename: null parameter");
    			return false;
    		}
    
    
    		File file = new File(f.filePath);
    		String newPath = Util.makePath(Util.getPathFromFilepath(f.filePath),
    				newName);
    		final boolean needScan = file.isFile();
    		try {
    			boolean ret = file.renameTo(new File(newPath));
    			if (ret) {
    				if (needScan) {
    					mOperationListener.onFileChanged(f.filePath);
    				}
    				mOperationListener.onFileChanged(newPath);
    			}
    			return ret;
    		} catch (SecurityException e) {
    			Log.e(LOG_TAG, "Fail to rename file," + e.toString());
    		}
    		return false;
    	}
    
    
    	//删除若干文件,先copy文件集合,再异步执行删除操作,删除完成后,有通知
    	public boolean Delete(ArrayList<FileInfo> files) {
    		copyFileList(files);
    		asnycExecute(new Runnable() {
    			@Override
    			public void run() {
    				for (FileInfo f : mCurFileNameList) {
    					DeleteFile(f);
    				}
    
    
    				mOperationListener.onFileChanged(Environment
    						.getExternalStorageDirectory().getAbsolutePath());
    
    
    				clear();
    			}
    		});
    		return true;
    	}
    
    
    	//删除1个文件
    	protected void DeleteFile(FileInfo f) {
    		if (f == null) {
    			Log.e(LOG_TAG, "DeleteFile: null parameter");
    			return;
    		}
    
    
    		File file = new File(f.filePath);
    		boolean directory = file.isDirectory();
    		if (directory) {
    			for (File child : file.listFiles(mFilter)) {
    				if (Util.isNormalFile(child.getAbsolutePath())) {
    					DeleteFile(Util.GetFileInfo(child, mFilter, true));
    				}
    			}
    		}
    
    
    		file.delete();
    
    
    		Log.v(LOG_TAG, "DeleteFile >>> " + f.filePath);
    	}
    
    
    	//执行1个文件的拷贝,如果文件是目录,拷贝整个目录,可能有递归Copy
    	private void CopyFile(FileInfo f, String dest) {
    		if (f == null || dest == null) {
    			Log.e(LOG_TAG, "CopyFile: null parameter");
    			return;
    		}
    
    
    		File file = new File(f.filePath);
    		if (file.isDirectory()) {
    
    
    			// directory exists in destination, rename it
    			String destPath = Util.makePath(dest, f.fileName);
    			File destFile = new File(destPath);
    			int i = 1;
    			while (destFile.exists()) {
    				destPath = Util.makePath(dest, f.fileName + " " + i++);
    				destFile = new File(destPath);
    			}
    
    
    			for (File child : file.listFiles(mFilter)) {
    				if (!child.isHidden()
    						&& Util.isNormalFile(child.getAbsolutePath())) {
    					CopyFile(Util.GetFileInfo(child, mFilter, Settings
    							.instance().getShowDotAndHiddenFiles()), destPath);
    				}
    			}
    		} else {
    			String destFile = Util.copyFile(f.filePath, dest);
    		}
    		Log.v(LOG_TAG, "CopyFile >>> " + f.filePath + "," + dest);
    	}
    
    
    	//移动文件,通过重命名的方式,移动的
    	private boolean MoveFile(FileInfo f, String dest) {
    		Log.v(LOG_TAG, "MoveFile >>> " + f.filePath + "," + dest);
    
    
    		if (f == null || dest == null) {
    			Log.e(LOG_TAG, "CopyFile: null parameter");
    			return false;
    		}
    
    
    		File file = new File(f.filePath);
    		String newPath = Util.makePath(dest, f.fileName);
    		try {
    			return file.renameTo(new File(newPath));
    		} catch (SecurityException e) {
    			Log.e(LOG_TAG, "Fail to move file," + e.toString());
    		}
    		return false;
    	}
    
    
    	//把文件集合copy到mCurFileNameList中,同步~
    	private void copyFileList(ArrayList<FileInfo> files) {
    		synchronized (mCurFileNameList) {
    			mCurFileNameList.clear();
    			for (FileInfo f : files) {
    				mCurFileNameList.add(f);
    			}
    		}
    	}
    
    
    }

  • 相关阅读:
    Spring2.5.6学习笔记DI的两种注入方式
    hsqldb2.2.9文档学习笔记之使用hsqldb
    Spring2.5.6学习笔记实例化bean的几种方法
    eclipse4.2插件开发之Hello!EclipsePlugin
    spring boot redis 多数据源配置 spring boot data redis
    docker安装mysql
    docker安装rabbitmq
    docker命令积累
    mysql8 免安装版 下载安装
    docker安装nginx
  • 原文地址:https://www.cnblogs.com/qitian1/p/6462644.html
Copyright © 2011-2022 走看看