文件操作是非常通用的,注释都写在源代码中了,不多说~
需要特别说明的是,任务的异步执行和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);
}
}
} }

小米开源文件管理器MiCodeFileExplorer-源码研究(4)-文件操作工具类FileOperationHelper的更多相关文章

  1. 小米开源文件管理器MiCodeFileExplorer-源码研究(0)-初步研究

    2011年对着书本Android应用开发揭秘,写了2个月的HelloWorld.   现在想复习并深入,我没有耐心再去一点点地敲代码了.   4年前自己是个学生,实习,现在有工作,只能业余时间研究. ...

  2. Android开源项目 Universal imageloader 源码研究之Lru算法

    https://github.com/nostra13/Android-Universal-Image-Loader universal imageloader 源码研究之Lru算法 LRU - Le ...

  3. 小米开源文件管理器MiCodeFileExplorer-源码研究(6)-媒体文件MediaFile和文件类型MimeUtils

    接着之前的第4篇,本篇的2个类,仍然是工具类.MediaFile,媒体文件,定义了一大堆的常量,真正的有用的方法就几个.isAudioFileType.isVideoFileType之类的. Mime ...

  4. 小米开源文件管理器MiCodeFileExplorer-源码研究(1)-2个模型Model

    上篇说到,把小米的Java代码整理成了5个包,其中1个是net.micode.fileexplorer.model.这个包就2个模型类,最基本了,FileInfo和FavoriteItem. pack ...

  5. 小米开源文件管理器MiCodeFileExplorer-源码研究(5)-AsyncTask异步任务

    说明:本文的文字和代码,主要来自于网上的2篇文章. 第4篇的时候,提到了异步任务AsyncTask. 网上找了2篇文章学习下,copy网友的代码,稍微改了几个字,运行成功了. 在开发Android移动 ...

  6. 开源播放器ijkplayer源码结构

    ijkplayer核心源码主要在ijkmedia文件夹下ijkplayer.ijksdl及ijkutils. 注:tag k0.3.1 player: remove ijkutil android相关 ...

  7. 小米开源文件管理器MiCodeFileExplorer-源码研究(9)-入口分析

    AndroidManifest.xml是Android应用程序最重要的配置文件. 入口文件和intent-filter <application android:icon="@draw ...

  8. 小米开源文件管理器MiCodeFileExplorer-源码研究(2)-2个单实例工具类

    从本篇开始,讲解net.micode.fileexplorer.util工具包中的类.这个包下的类,功能也比较单一和独立.很多代码的思想和实现,可以用于JavaWeb和Android等多种环境中. 一 ...

  9. 小米开源文件管理器MiCodeFileExplorer-源码研究(3)-使用最多的工具类Util

    Util.java,使用最广泛~代码中很多地方,都写了注释说明~基本不需要怎么解释了~ package net.micode.fileexplorer.util; import java.io.Fil ...

随机推荐

  1. [国家集训队]整数的lqp拆分 数学推导 打表找规律

    题解: 考场上靠打表找规律切的题,不过严谨的数学推导才是本题精妙所在:求:$\sum\prod_{i=1}^{m}F_{a{i}}$ 设 $f(i)$ 为 $N=i$ 时的答案,$F_{i}$ 为斐波 ...

  2. vue引入iconfont阿里字体图标库以及报错解决

    下载阿里的字体图标库文件,放在\src\assets\font文件夹下面. 安装style-loader,css-loader和file-loader (或url-loader)  ,记得--save ...

  3. ArchLinux dwm的安装和配置

    dwm官网:https://dwm.suckless.org/ dwm是一个简洁的平铺式窗口管理器 配置简单,使用便捷,没有多少依赖,占用内存非常小 总之dwm正合口味 安装方法 首先在官网下载dwm ...

  4. Linux Shell脚本编程-函数

    函数介绍  定义:把一段独立功能的的代码当做一个整体,并为之一个名字,命名的代码段,此即为函数:  功能:函数function是由若干条shell命令组成的语句块,实现代码重用和模块化编程.  注意: ...

  5. 洛谷 P2015 二叉苹果树 && caioj1107 树形动态规划(TreeDP)2:二叉苹果树

    这道题一开始是按照caioj上面的方法写的 (1)存储二叉树用结构体,记录左儿子和右儿子 (2)把边上的权值转化到点上,离根远的点上 (3)用记忆化搜索,枚举左右节点分别有多少个点,去递归 这种写法有 ...

  6. jquery中$.get()提交和$.post()提交有区别

    jquery中$.get()提交和$.post()提交有区别吗? 相同点:都是异步请求的方式来获取服务端的数据: 异同点: 1.请求方式不同:$.get() 方法使用GET方法来进行异步请求的.$.p ...

  7. POJ——T 1986 Distance Queries

    http://poj.org/problem?id=1986 Time Limit: 2000MS   Memory Limit: 30000K Total Submissions: 14383   ...

  8. Intellij Idea创建的第一个JavaWeb程序

    第一个JavaWeb程序 1. 创建 2. 目录结构 src目录用于放java源文件,web目录用于放web资源,WEB-INF是Java web应用固定的存放配置及类库的目录,index.jsp是我 ...

  9. 分享关于浏览器对象 history对象

    window.history.forward() == window.history.go(-1) //返回下一页 window.history.back() == window.history.go ...

  10. JS — 对象的基本操作

    JS面向对象系列教程 — 对象的基本操作 面向对象概述  面向对象(Object Oriented)简称OO,它是一种编程思维,用于指导我们如何应对各种复杂的开发场景. 这里说的对象(Object) ...