文件管理器源码分析(二)

/**
 * 文件操作工具,执行文件的创建、移、粘贴、重命、删除等
 * 任务异步执IOperationProgressListener
 拷贝和删除等操作,比较费时,采用异步执行的方式~
 http://blog.csdn.net/xufenghappy6/article/details/7343899
 异步执+通知 比较流行的,比步等待很多时候好。
 */
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;
    }
    /**
     * 能否移走,假pathC:/a/b”,f.filePathC:/a/b/c/d.png”,能移走
     * 感覺太靠譜,爲啥不能移動到文件的上層目錄呢?
     * @param path
     * @return
     */
    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);
            }
        }
    }
}
时间: 2024-10-11 13:20:36

文件管理器源码分析(二)的相关文章

文件管理器源码分析(一)

Aboutmillet file management source code analysis Openthe file manager millet, we will soon see the interface as shownbelow: Amongthem, will be a variety of document classification. And show thenumber of each file. Androidframework of the MediaStore h

文件管理器源码分析(五)

/** * 这个文件夹里面存储的内容是app2sd产生的文件夹,也就是是你手机上所有安装到SD卡的应用程序的缓存文件夹. * androidsecure文件夹可以删除吗? *如果删除之后,软件不能正常使用,和系统没有关系. *删的话除了会可能导致移动至sd卡的程序损坏,数据丢失,并不会造成什么严重后果. * 只要把移动到sd卡的损坏程序卸载,重装,手机就完全没有损伤,文件夹也会在再次app2sd时自动重建的. */ public class Util { private static Strin

文件管理器源码分析(三)

//存储favorite数据,到数据库 //SQLiteOpenHelper是一个帮助管理数据库和版本的工具类. //通过继承并重载方法,快速实现了我们自己的Favorite表的CRUD. //怎么感觉和FileOperationHelper类似,仍然是CRUD,只不过1个是数据库中的,1个是文件的. public class FavoriteDatabaseHelper extends SQLiteOpenHelper { //下面6个字段是数据库的名字和版本号.表的名字和3个字段 priva

linux调度器源码分析 - 初始化(二)

本文为原创,转载请注明:http://www.cnblogs.com/tolimit/ 引言 上期文章linux调度器源码分析 - 概述(一)已经把调度器相关的数据结构介绍了一遍,本篇着重通过代码说明调度器在系统启动初始化阶段是如何初始化和工作的.通过上期文章我们知道,在多核CPU和SMP系统中,每个CPU(多核COU中的每个核)都有自己的struct rq队列,而rq队列中又有着自己的struct cfs_rq和struct rt_rq.在初始化时就是对这三个结构进行初始化. init_tas

netty 源码分析二

以服务端启动,接收客户端连接整个过程为例分析, 简略分为 五个过程: 1.NioServerSocketChannel 管道生成, 2.NioServerSocketChannel 管道完成初始化, 3.NioServerSocketChannel注册至Selector选择器, 4.NioServerSocketChannel管道绑定到指定端口,启动服务 5.NioServerSocketChannel接受客户端的连接,进行相应IO操作 Ps:netty内部过程远比这复杂,简略记录下方便以后回忆

[Android]Volley源码分析(二)Cache

Cache作为Volley最为核心的一部分,Volley花了重彩来实现它.本章我们顺着Volley的源码思路往下,来看下Volley对Cache的处理逻辑. 我们回想一下昨天的简单代码,我们的入口是从构造一个Request队列开始的,而我们并不直接调用new来构造,而是将控制权反转给Volley这个静态工厂来构造. com.android.volley.toolbox.Volley: public static RequestQueue newRequestQueue(Context conte

哇!板球 源码分析二

游戏主页面布局 创建屏下Score标签 pLabel = CCLabelTTF::create("Score", "Arial", TITLE_FONT_SIZE); //分数标签 //设置标签字体的颜色 pLabel->setColor (ccc3(0, 0, 0)); //设置文本标签的位置 pLabel->setPosition ( ccp ( SCORE_X, //X坐标 SCORE_Y //Y坐标 ) ); //将文本标签添加到布景中 this

baksmali和smali源码分析(二)

这一节,主要介绍一下 baksmali代码的框架. 我们经常在反编译android apk包的时候使用apktool这个工具,其实本身这个工具里面对于dex文件解析和重新生成就是使用的baksmali 和smali这两个jar包其中 baksmali是将 dex文件转换成便于阅读的smali文件的,具体使用命令如下:java -jar baksmali.jar classes.dex -o myout其中myout是输出的文件夹 而smali是将smali文件重新生成回 dex文件的具体使用的命

【梦幻连连连】源码分析(二)

转载请注明出处:http://blog.csdn.net/oyangyufu/article/details/24736711 GameLayer场景界面效果: 源码分析: GameLayer场景初始化,主要是初始化加载界面及背景音乐 bool GameLayer::init() { float dt=0.0f; if ( !CCLayerColor::initWithColor(ccc4(255, 255, 255, 255))) { return false; } this->initLoa