cn.edu.sdust.silence.itransfer.ui.file.FileManager.java Source code

Java tutorial

Introduction

Here is the source code for cn.edu.sdust.silence.itransfer.ui.file.FileManager.java

Source

/*
Open Manager For Tablets, an open source file manager for the Android system
Copyright (C) 2011  Joe Berria <nexesdevelopment@gmail.com>
    
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
    
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.
    
You should have received a copy of the GNU General Public License
along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

package cn.edu.sdust.silence.itransfer.ui.file;

import android.util.Log;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Stack;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import java.util.zip.ZipOutputStream;

/**
 * This class is completely modular, which is to say that it has
 * no reference to the any GUI activity. This class could be taken
 * and placed into in other java (not just Android) project and work.
 * <br>
 * <br>
 * This class handles all file and folder operations on the system.
 * This class dictates how files and folders are copied/pasted, (un)zipped
 * renamed and searched. The EventHandler class will generally call these
 * methods and have them performed in a background thread. Threading is not
 * done in this class.
 *
 * @author Joe Berria
 */
public class FileManager {
    private static final int BUFFER = 2048;

    //declare the type of that use the sort files
    private static final int SORT_NONE = 0;
    private static final int SORT_ALPHA = 1;
    private static final int SORT_TYPE = 2;
    private static final int SORT_SIZE = 3;

    private boolean mShowHiddenFiles = false;
    private int mSortType = SORT_ALPHA;
    private long mDirSize = 0;

    //the dir stack, current dir alawys on the top of the stack
    private Stack<String> mPathStack;

    //all the file's or dir's name on the current dir
    private ArrayList<String> mDirContent;

    /**
     * Constructs an object of the class
     * <br>
     * this class uses a stack to handle the navigation of directories.
     */
    public FileManager() {
        mDirContent = new ArrayList<String>();
        mPathStack = new Stack<String>();

        mPathStack.push("/");
        mPathStack.push(mPathStack.peek() + "sdcard");
    }

    /**
     * This will return a string of the current directory path
     *
     * @return the current directory
     */
    public String getCurrentDir() {
        return mPathStack.peek();
    }

    /**
     * This will return a string list of the current home path's content.
     *
     * @return the home directory
     */
    public ArrayList<String> setHomeDir(String name) {
        //This will eventually be placed as a settings item
        mPathStack.clear();
        mPathStack.push("/");
        mPathStack.push(name);

        return populate_list();
    }

    /**
     * This will determine if hidden files and folders will be visible to the
     * user.
     *
     * @param choice true if user is veiwing hidden files, false otherwise
     */
    public void setShowHiddenFiles(boolean choice) {
        mShowHiddenFiles = choice;
    }

    /**
     * @param type
     */
    public void setSortType(int type) {
        mSortType = type;
    }

    /**
     * This will return a string that represents the path of the previous path
     *
     * @return returns the previous path
     */
    public ArrayList<String> getPreviousDir() {
        int size = mPathStack.size();

        if (size >= 2)
            mPathStack.pop();

        else if (size == 0)
            mPathStack.push("/");

        return populate_list();
    }

    public ArrayList<String> getCurrentDirContent() {
        return populate_list();
    }

    /**
     * @param path
     * @param isFullPath
     * @return
     */
    public ArrayList<String> getNextDir(String path, boolean isFullPath) {
        int size = mPathStack.size();

        if (!path.equals(mPathStack.peek()) && !isFullPath) {
            if (size == 1)
                mPathStack.push("/" + path);
            else
                mPathStack.push(mPathStack.peek() + "/" + path);
        } else if (!path.equals(mPathStack.peek()) && isFullPath) {
            mPathStack.push(path);
        }

        return populate_list();
    }

    /**
     * @param old    the file to be copied
     * @param newDir the directory to move the file to
     * @return
     */
    public int copyToDirectory(String old, String newDir) {
        File old_file = new File(old);
        File temp_dir = new File(newDir);
        byte[] data = new byte[BUFFER];
        int read = 0;

        if (old_file.isFile() && temp_dir.isDirectory() && temp_dir.canWrite()) {
            String file_name = old.substring(old.lastIndexOf("/"), old.length());
            File cp_file = new File(newDir + file_name);

            try {
                BufferedOutputStream o_stream = new BufferedOutputStream(new FileOutputStream(cp_file));
                BufferedInputStream i_stream = new BufferedInputStream(new FileInputStream(old_file));

                while ((read = i_stream.read(data, 0, BUFFER)) != -1)
                    o_stream.write(data, 0, read);

                o_stream.flush();
                i_stream.close();
                o_stream.close();

            } catch (FileNotFoundException e) {
                Log.e("FileNotFoundException", e.getMessage());
                return -1;

            } catch (IOException e) {
                Log.e("IOException", e.getMessage());
                return -1;
            }

        } else if (old_file.isDirectory() && temp_dir.isDirectory() && temp_dir.canWrite()) {
            String files[] = old_file.list();
            String dir = newDir + old.substring(old.lastIndexOf("/"), old.length());
            int len = files.length;

            if (!new File(dir).mkdir())
                return -1;

            for (int i = 0; i < len; i++)
                copyToDirectory(old + "/" + files[i], dir);

        } else if (!temp_dir.canWrite())
            return -1;

        return 0;
    }

    /**
     * @param zipName
     * @param toDir
     * @param fromDir
     */
    public void extractZipFilesFromDir(String zipName, String toDir, String fromDir) {
        if (!(toDir.charAt(toDir.length() - 1) == '/'))
            toDir += "/";
        if (!(fromDir.charAt(fromDir.length() - 1) == '/'))
            fromDir += "/";

        String org_path = fromDir + zipName;

        extractZipFiles(org_path, toDir);
    }

    /**
     * @param zip_file
     * @param directory
     */
    public void extractZipFiles(String zip_file, String directory) {
        byte[] data = new byte[BUFFER];
        String name, path, zipDir;
        ZipEntry entry;
        ZipInputStream zipstream;

        if (!(directory.charAt(directory.length() - 1) == '/'))
            directory += "/";

        if (zip_file.contains("/")) {
            path = zip_file;
            name = path.substring(path.lastIndexOf("/") + 1, path.length() - 4);
            zipDir = directory + name + "/";

        } else {
            path = directory + zip_file;
            name = path.substring(path.lastIndexOf("/") + 1, path.length() - 4);
            zipDir = directory + name + "/";
        }

        new File(zipDir).mkdir();

        try {
            zipstream = new ZipInputStream(new FileInputStream(path));

            while ((entry = zipstream.getNextEntry()) != null) {
                String buildDir = zipDir;
                String[] dirs = entry.getName().split("/");

                if (dirs != null && dirs.length > 0) {
                    for (int i = 0; i < dirs.length - 1; i++) {
                        buildDir += dirs[i] + "/";
                        new File(buildDir).mkdir();
                    }
                }

                int read = 0;
                FileOutputStream out = new FileOutputStream(zipDir + entry.getName());
                while ((read = zipstream.read(data, 0, BUFFER)) != -1)
                    out.write(data, 0, read);

                zipstream.closeEntry();
                out.close();
            }

        } catch (FileNotFoundException e) {
            e.printStackTrace();

        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * @param path
     */
    public void createZipFile(String path) {
        File dir = new File(path);
        String[] list = dir.list();
        String name = path.substring(path.lastIndexOf("/"), path.length());
        String _path;

        if (!dir.canRead() || !dir.canWrite())
            return;

        int len = list.length;

        if (path.charAt(path.length() - 1) != '/')
            _path = path + "/";
        else
            _path = path;

        try {
            ZipOutputStream zip_out = new ZipOutputStream(
                    new BufferedOutputStream(new FileOutputStream(_path + name + ".zip"), BUFFER));

            for (int i = 0; i < len; i++)
                zip_folder(new File(_path + list[i]), zip_out);

            zip_out.close();

        } catch (FileNotFoundException e) {
            Log.e("File not found", e.getMessage());

        } catch (IOException e) {
            Log.e("IOException", e.getMessage());
        }
    }

    /**
     * @param filePath
     * @param newName
     * @return
     */
    public int renameTarget(String filePath, String newName) {
        File src = new File(filePath);
        String ext = "";
        File dest;

        if (src.isFile())
            /*get file extension*/
            ext = filePath.substring(filePath.lastIndexOf("."), filePath.length());

        if (newName.length() < 1)
            return -1;

        String temp = filePath.substring(0, filePath.lastIndexOf("/"));

        dest = new File(temp + "/" + newName + ext);
        if (src.renameTo(dest))
            return 0;
        else
            return -1;
    }

    /**
     * @param path
     * @param name
     * @return
     */
    public int createDir(String path, String name) {
        int len = path.length();

        if (len < 1 || len < 1)
            return -1;

        if (path.charAt(len - 1) != '/')
            path += "/";

        if (new File(path + name).mkdir())
            return 0;

        return -1;
    }

    /**
     * The full path name of the file to delete.
     *
     * @param path name
     * @return
     */
    public int deleteTarget(String path) {
        File target = new File(path);

        if (target.exists() && target.isFile() && target.canWrite()) {
            target.delete();
            return 0;
        } else if (target.exists() && target.isDirectory() && target.canRead()) {
            String[] file_list = target.list();

            if (file_list != null && file_list.length == 0) {
                target.delete();
                return 0;

            } else if (file_list != null && file_list.length > 0) {

                for (int i = 0; i < file_list.length; i++) {
                    File temp_f = new File(target.getAbsolutePath() + "/" + file_list[i]);

                    if (temp_f.isDirectory())
                        deleteTarget(temp_f.getAbsolutePath());
                    else if (temp_f.isFile())
                        temp_f.delete();
                }
            }
            if (target.exists())
                if (target.delete())
                    return 0;
        }
        return -1;
    }

    /**
     * @param name
     * @return
     */
    public boolean isDirectory(String name) {
        return new File(mPathStack.peek() + "/" + name).isDirectory();
    }

    /**
     * converts integer from wifi manager to an IP address.
     *
     * @param
     * @return
     */
    public static String integerToIPAddress(int ip) {
        String ascii_address = "";
        int[] num = new int[4];

        num[0] = (ip & 0xff000000) >> 24;
        num[1] = (ip & 0x00ff0000) >> 16;
        num[2] = (ip & 0x0000ff00) >> 8;
        num[3] = ip & 0x000000ff;

        ascii_address = num[0] + "." + num[1] + "." + num[2] + "." + num[3];

        return ascii_address;
    }

    /**
     * @param
     * @param
     * @return
     */
    public ArrayList<String> searchInDirectory(String dir, String pathName) {
        ArrayList<String> names = new ArrayList<String>();
        search_file(dir, pathName, names);

        return names;
    }

    /**
     * @param path
     * @return
     */
    public long getDirSize(String path) {
        get_dir_size(new File(path));

        return mDirSize;
    }

    private static final Comparator alph = new Comparator<String>() {
        @Override
        public int compare(String arg0, String arg1) {
            return arg0.toLowerCase().compareTo(arg1.toLowerCase());
        }
    };

    private final Comparator size = new Comparator<String>() {
        @Override
        public int compare(String arg0, String arg1) {
            String dir = mPathStack.peek();
            Long first = new File(dir + "/" + arg0).length();
            Long second = new File(dir + "/" + arg1).length();

            return first.compareTo(second);
        }
    };

    private final Comparator type = new Comparator<String>() {
        @Override
        public int compare(String arg0, String arg1) {
            String ext = null;
            String ext2 = null;
            int ret;

            try {
                ext = arg0.substring(arg0.lastIndexOf(".") + 1, arg0.length()).toLowerCase();
                ext2 = arg1.substring(arg1.lastIndexOf(".") + 1, arg1.length()).toLowerCase();

            } catch (IndexOutOfBoundsException e) {
                return 0;
            }
            ret = ext.compareTo(ext2);

            if (ret == 0)
                return arg0.toLowerCase().compareTo(arg1.toLowerCase());

            return ret;
        }
    };

    /* (non-Javadoc)
     * this function will take the string from the top of the directory stack
     * and list all files/folders that are in it and return that list so
     * it can be displayed. Since this function is called every time we need
     * to update the the list of files to be shown to the user, this is where
     * we do our sorting (by type, alphabetical, etc).
     *
     * @return
     */
    private ArrayList<String> populate_list() {

        if (!mDirContent.isEmpty())
            mDirContent.clear();

        File file = new File(mPathStack.peek());

        if (file.exists() && file.canRead()) {
            String[] list = file.list();
            int len = list.length;

            /* add files/folder to arraylist depending on hidden status */
            for (int i = 0; i < len; i++) {
                if (!mShowHiddenFiles) {
                    if (list[i].toString().charAt(0) != '.')
                        mDirContent.add(list[i]);

                } else {
                    mDirContent.add(list[i]);
                }
            }

            /* sort the arraylist that was made from above for loop */
            switch (mSortType) {
            case SORT_NONE:
                //no sorting needed
                break;

            case SORT_ALPHA:
                Object[] tt = mDirContent.toArray();
                mDirContent.clear();

                Arrays.sort(tt, alph);

                //                    for (Object a : tt) {
                //                        mDirContent.add((String) a);
                //                    }
                String path = mPathStack.peek();
                for (Object a : tt) {
                    if (new File(path + "/" + (String) a).isDirectory())
                        mDirContent.add((String) a);
                }

                for (Object a : tt) {
                    if (new File(path + "/" + (String) a).isFile())
                        mDirContent.add((String) a);
                }

                break;

            case SORT_SIZE:
                int index = 0;
                Object[] size_ar = mDirContent.toArray();
                String dir = mPathStack.peek();

                Arrays.sort(size_ar, size);

                mDirContent.clear();
                for (Object a : size_ar) {
                    if (new File(dir + "/" + (String) a).isDirectory())
                        mDirContent.add(index++, (String) a);
                    else
                        mDirContent.add((String) a);
                }
                break;

            case SORT_TYPE:
                int dirindex = 0;
                Object[] type_ar = mDirContent.toArray();
                String current = mPathStack.peek();

                Arrays.sort(type_ar, type);
                mDirContent.clear();

                for (Object a : type_ar) {
                    if (new File(current + "/" + (String) a).isDirectory())
                        mDirContent.add(dirindex++, (String) a);
                    else
                        mDirContent.add((String) a);
                }
                break;
            }

        } else {
            mDirContent.add("Emtpy");
        }

        return mDirContent;
    }

    /*
     *
     * @param file
     * @param zout
     * @throws IOException
     */
    private void zip_folder(File file, ZipOutputStream zout) throws IOException {
        byte[] data = new byte[BUFFER];
        int read;

        if (file.isFile()) {
            ZipEntry entry = new ZipEntry(file.getName());
            zout.putNextEntry(entry);
            BufferedInputStream instream = new BufferedInputStream(new FileInputStream(file));

            while ((read = instream.read(data, 0, BUFFER)) != -1)
                zout.write(data, 0, read);

            zout.closeEntry();
            instream.close();

        } else if (file.isDirectory()) {
            String[] list = file.list();
            int len = list.length;

            for (int i = 0; i < len; i++)
                zip_folder(new File(file.getPath() + "/" + list[i]), zout);
        }
    }

    /*
     *
     * @param path
     */
    private void get_dir_size(File path) {
        File[] list = path.listFiles();
        int len;

        if (list != null) {
            len = list.length;

            for (int i = 0; i < len; i++) {
                try {
                    if (list[i].isFile() && list[i].canRead()) {
                        mDirSize += list[i].length();

                    } else if (list[i].isDirectory() && list[i].canRead() && !isSymlink(list[i])) {
                        get_dir_size(list[i]);
                    }
                } catch (IOException e) {
                    Log.e("IOException", e.getMessage());
                }
            }
        }
    }

    // Inspired by org.apache.commons.io.FileUtils.isSymlink()
    private static boolean isSymlink(File file) throws IOException {
        File fileInCanonicalDir = null;
        if (file.getParent() == null) {
            fileInCanonicalDir = file;
        } else {
            File canonicalDir = file.getParentFile().getCanonicalFile();
            fileInCanonicalDir = new File(canonicalDir, file.getName());
        }
        return !fileInCanonicalDir.getCanonicalFile().equals(fileInCanonicalDir.getAbsoluteFile());
    }

    /*
     * (non-JavaDoc)
     * I dont like this method, it needs to be rewritten. Its hacky in that
     * if you are searching in the root dir (/) then it is not going to be treated
     * as a recursive method so the user dosen't have to sit forever and wait.
     *
     * I will rewrite this ugly method.
     *
     * @param dir      directory to search in
     * @param fileName   filename that is being searched for
     * @param n         ArrayList to populate results
     */
    private void search_file(String dir, String fileName, ArrayList<String> n) {
        File root_dir = new File(dir);
        String[] list = root_dir.list();

        if (list != null && root_dir.canRead()) {
            int len = list.length;

            for (int i = 0; i < len; i++) {
                File check = new File(dir + "/" + list[i]);
                String name = check.getName();

                if (check.isFile() && name.toLowerCase().contains(fileName.toLowerCase())) {
                    n.add(check.getPath());
                } else if (check.isDirectory()) {
                    if (name.toLowerCase().contains(fileName.toLowerCase()))
                        n.add(check.getPath());

                    else if (check.canRead() && !dir.equals("/"))
                        search_file(check.getAbsolutePath(), fileName, n);
                }
            }
        }
    }
}