File 相关工具类

/**
 * File 相关工具类
 */
public class FileUtil {
    private final String TAG = FileUtil.class.getSimpleName();

    private FileUtil() {
    }

    /***********************************************************************************************
     ****  公用方法
     **********************************************************************************************/

    /**
     * 判断是否有 SD 卡
     *
     * @return {@code true}: 有<br>{@code false}: 沒有
     */
    public static boolean isHasSdCard() {
        if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
            return true;
        }
        return false;
    }

    /**
     * 获取 SD 卡路径
     *
     * @return SD 卡路径
     */
    public static String getSdCardPath() {
        return Environment.getExternalStorageDirectory().toString();
    }

    /**
     * 判断是否是文件夹
     *
     * @param dirPath 文件路径
     * @return {@code true}: 是<br>{@code false}: 否
     */
    public static boolean isDir(String dirPath) {
        return isDir(new File(dirPath));
    }

    /**
     * 判断是否是文件夹
     *
     * @param dir 文件对象
     * @return {@code true}: 是<br>{@code false}: 否
     */
    public static boolean isDir(File dir) {
        if (dir == null || !dir.exists()) {
            return false;
        }
        return dir.isDirectory();
    }

    /**
     * 判断是否是文件
     *
     * @param filePath 文件路径
     * @return {@code true}: 是<br>{@code false}: 否
     */
    public static boolean isFile(String filePath) {
        return isFile(new File(filePath));
    }

    /**
     * 判断是否是文件
     *
     * @param file 文件对象
     * @return {@code true}: 是<br>{@code false}: 否
     */
    public static boolean isFile(File file) {
        if (file == null || !file.exists()) {
            return false;
        }
        return file.isFile();
    }

    /***********************************************************************************************
     ****  单例操作
     **********************************************************************************************/

    public static FileUtil getInstance() {
        return FileUtilHolder.INSTANCE;
    }

    private static class FileUtilHolder {
        private static final FileUtil INSTANCE = new FileUtil();
    }

    /**
     * 创建文件夹 (你必须先创建文件夹,才能创建文件,否则会报“找不到路径”)
     *
     * @param path 创建的文件夹的路径
     * @return {@code true}: 创建成功<br>{@code false}: 创建失败
     */
    public boolean createDir(String path) {
        if (TextUtils.isEmpty(path)) return false;
        boolean isSuccess;
        File file = new File(path);
        if (!file.exists()) {
            // 如果文件夹已经存在执行此方法会返回false
            isSuccess = file.mkdirs();
        } else {
            isSuccess = true;
        }
        return isSuccess;
    }

    /**
     * 创建文件
     *
     * @param path 创建的文件的路径
     * @return {@code true}: 创建成功<br>{@code false}: 创建失败
     */
    public boolean createFile(String path) {
        if (TextUtils.isEmpty(path)) return false;
        boolean isSuccess = false;
        File file = new File(path);
        if (!file.exists()) {
            try {
                // 如果文件已经存在执行此方法会返回 false
                isSuccess = file.createNewFile();
            } catch (Exception e) {
                e.printStackTrace();
            }
        } else {
            isSuccess = true;
        }
        return isSuccess;
    }


    /***********************************************************************************************
     ****  IO 操作
     **********************************************************************************************/

    /**
     * 保存 String 数据
     *
     * @param key   保存 String 数据的文件的路径
     * @param value 保存的 String 数据
     * @throws IOException
     */
    public void put(String key, String value) {
        File file = new File(key);
        BufferedWriter out = null;
        try {
            out = new BufferedWriter(new FileWriter(file), 1024);
            out.write(value);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (out != null) {
                try {
                    out.flush();
                    out.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * 读取 String 数据
     *
     * @param key 保存 String 数据的文件的路径
     * @return 保存的 String 数据
     */
    public String getAsString(String key) {
        File file = new File(key);
        if (!file.exists()) {
            return null;
        }
        BufferedReader in = null;
        try {
            in = new BufferedReader(new FileReader(file));
            String readString = "";
            String currentLine;
            while ((currentLine = in.readLine()) != null) {
                readString += currentLine;
            }
            return readString;
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        } finally {
            if (in != null) {
                try {
                    in.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * 保存 byte[]
     *
     * @param key   保存 byte[] 数据的文件的路径
     * @param value 保存的 byte[] 数据
     */
    public void put(String key, byte[] value) {
        File file = new File(key);
        FileOutputStream out = null;
        try {
            out = new FileOutputStream(file);
            out.write(value);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (out != null) {
                try {
                    out.flush();
                    out.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * 读取 byte[]
     *
     * @param key 保存 byte[] 数据的文件的路径
     * @return 保存的 byte[] 数据
     */
    public byte[] getAsBinary(String key) {
        File file = new File(key);
        if (!file.exists()) {
            return null;
        }
        byte[] byteArray = null;
        FileInputStream fis = null;
        ByteArrayOutputStream baos = null;
        try {
            fis = new FileInputStream(file);
            baos = new ByteArrayOutputStream(1024);
            byte[] b = new byte[1024];
            int n;
            while ((n = fis.read(b)) != -1) {
                baos.write(b, 0, n);
            }
            byteArray = baos.toByteArray();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (fis != null) {
                    fis.close();
                }
                if (baos != null) {
                    baos.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return byteArray;
    }

    /**
     * 保存序列化对象
     *
     * @param key   保存序列化对象数据的文件的路径
     * @param value 保存的序列化对象数据
     */
    public void put(String key, Serializable value) {
        ByteArrayOutputStream baos = null;
        ObjectOutputStream oos = null;
        try {
            baos = new ByteArrayOutputStream();
            oos = new ObjectOutputStream(baos);
            oos.writeObject(value);
            byte[] data = baos.toByteArray();
            put(key, data);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (baos != null) {
                try {
                    baos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (oos != null) {
                try {
                    oos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * 读取序列化对象
     *
     * @param key 保存序列化对象数据的文件的路径
     * @return 保存的序列化对象数据
     */
    public Object getAsObject(String key) {
        ByteArrayInputStream bais = null;
        ObjectInputStream ois = null;
        try {
            byte[] data = getAsBinary(key);
            if (data == null || data.length == 0) return null;
            bais = new ByteArrayInputStream(data);
            ois = new ObjectInputStream(bais);
            Object obj = ois.readObject();
            return obj;
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
            return null;
        } finally {
            if (bais != null) {
                try {
                    bais.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (ois != null) {
                try {
                    ois.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * 保存 bitmap 数据
     *
     * @param key   保存 bitmap 数据的文件的路径
     * @param value 保存的 bitmap 数据
     */
    public void put(String key, Bitmap value) {
        put(key, bitmap2Byte(value));
    }

    /**
     * 读取 bitmap 数据
     *
     * @param key 保存 bitmap 数据的文件的路径
     * @return 保存的 bitmap 数据
     */
    public Bitmap getAsBitmap(String key) {
        if (getAsBinary(key) == null) return null;
        return byte2Bitmap(getAsBinary(key));
    }

    private byte[] bitmap2Byte(Bitmap bmp) {
        if (bmp == null) return null;
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        bmp.compress(Bitmap.CompressFormat.JPEG, 100, baos);
        return baos.toByteArray();
    }

    private Bitmap byte2Bitmap(byte[] bytes) {
        if (bytes.length == 0) {
            return null;
        }
        return BitmapFactory.decodeByteArray(bytes, 0, bytes.length);
    }


    /***********************************************************************************************
     ****  拷贝文件以及文件夹到指定路径
     **********************************************************************************************/

    /**
     * 拷贝文件到指定路径
     *
     * @param oldPath 被拷贝文件的原始路径
     * @param newPath 文件被拷贝后的所在路径
     */
    public void copyFile(@NonNull String oldPath, @NonNull String newPath) {
        int bytesum = 0;
        int byteread = 0;
        File oldfile = new File(oldPath);
        FileInputStream fis = null;
        FileOutputStream fos = null;
        if (oldfile.exists()) {
            try {
                fis = new FileInputStream(oldPath);
                fos = new FileOutputStream(newPath);
                byte[] buffer = new byte[1024];
                while ((byteread = fis.read(buffer)) != -1) {
                    bytesum += byteread;
                    fos.write(buffer, 0, byteread);
                }
                LogUtil.d(TAG, "copy file success, the total size of the file is ========> " + bytesum + " byte");
            } catch (IOException e) {
                LogUtil.e(TAG, "Copy file error ========> " + e.toString());
                e.printStackTrace();
            } finally {
                if (fis != null) {
                    try {
                        fis.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
                if (fos != null) {
                    try {
                        fos.flush();
                        fos.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        } else {
            LogUtil.e(TAG, "Copy file error ========> source file does not exist!");
        }
    }

    /**
     * 拷贝文件夹内容到指定位置
     *
     * @param oldPath 被拷贝文件夹的原始路径
     * @param newPath 文件夹被拷贝后的所在路径
     */
    public void copyDir(@NonNull String oldPath, @NonNull String newPath) {
        try {
            (new File(newPath)).mkdirs();
            File oldDir = new File(oldPath);
            String[] fileNameList = oldDir.list();
            File temp = null;
            for (int i = 0; i < fileNameList.length; i++) {
                if (oldPath.endsWith(File.separator)) {
                    temp = new File(oldPath + fileNameList[i]);
                } else {
                    temp = new File(oldPath + File.separator + fileNameList[i]);
                }
                if (temp.isFile()) {
                    FileInputStream input = new FileInputStream(temp);
                    FileOutputStream output = null;
                    if (newPath.endsWith(File.separator)) {
                        output = new FileOutputStream(newPath + (temp.getName()).toString());
                    } else {
                        output = new FileOutputStream(newPath + File.separator + (temp.getName()).toString());
                    }
                    byte[] b = new byte[1024];
                    int len;
                    while ((len = input.read(b)) != -1) {
                        output.write(b, 0, len);
                    }
                    output.flush();
                    output.close();
                    input.close();
                } else {
                    String op = null, np = null;
                    if (oldPath.endsWith(File.separator)) {
                        op = oldPath + fileNameList[i];
                    } else {
                        op = oldPath + File.separator + fileNameList[i];
                    }
                    if (newPath.endsWith(File.separator)) {
                        np = newPath + fileNameList[i];
                    } else {
                        np = newPath + File.separator + fileNameList[i];
                    }
                    copyDir(op, np);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 获取指定文件夹中文件的数量
     *
     * @param dir   指定文件夹路径
     * @param isAll {@code true}: 获取所有的文件数量<br>{@code false}: 只获取第一级的文件数量
     * @return 文件的数量
     */
    public int getFileCount(String dir, boolean isAll) {
        if (TextUtils.isEmpty(dir)) return 0;
        int count = 0;
        if (!dir.endsWith(File.separator)) {
            dir = dir + File.separator;
        }
        File dirFile = new File(dir);
        if (!dirFile.exists() || !dirFile.isDirectory()) {
            return count;
        }
        File[] files = dirFile.listFiles();
        for (int i = 0; i < files.length; i++) {
            if (files[i].isFile()) {
                count += 1;
            } else {
                if (isAll) {
                    getFileCount(files[i].getAbsolutePath(), true);
                }
            }
        }
        return count;
    }

    /***********************************************************************************************
     ****  删除文件
     **********************************************************************************************/

    /**
     * 删除文件或文件夹
     *
     * @param path 文件或文件夹的路径
     * @return {@code true}: 删除失败<br>{@code false}: 删除成功
     */
    public boolean delete(String path) {
        return TextUtils.isEmpty(path) ? true : delete(new File(path));
    }

    /**
     * 删除文件或文件夹
     *
     * @param file 文件或文件夹
     * @return {@code true}: 删除失败<br>{@code false}: 删除成功
     */
    public boolean delete(File file) {
        if (file == null) return true;
        try {
            if (file.exists()) {
                if (file.isFile()) {
                    return deleteFile(file);
                } else {
                    return deleteDir(file);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
            LogUtil.e(TAG, "Failed to delete file ========> " + e.getMessage());
        }
        return false;
    }

    /**
     * 删除单个文件
     *
     * @param path 文件的路径
     * @return {@code true}: 删除失败<br>{@code false}: 删除成功
     */
    public boolean deleteFile(String path) {
        return TextUtils.isEmpty(path) ? true : deleteFile(new File(path));
    }

    /**
     * 删除单个文件
     *
     * @param file 文件
     * @return {@code true}: 删除失败<br>{@code false}: 删除成功
     */
    public boolean deleteFile(File file) {
        if (file != null && file.exists() && file.isFile()) {
            return file.delete();
        } else {
            return true;
        }
    }

    /**
     * 删除文件夹
     *
     * @param dir 文件夹的路径
     * @return {@code true}: 删除失败<br>{@code false}: 删除成功
     */
    public boolean deleteDir(String dir) {
        if (TextUtils.isEmpty(dir)) return true;
        // 如果文件夹路径不是以文件分隔符结尾,则在路径末尾自动添加文件分隔符
        if (!dir.endsWith(File.separator)) {
            dir = dir + File.separator;
        }
        return deleteDir(new File(dir));
    }

    /**
     * 删除文件夹
     *
     * @param fileDir 文件夹
     * @return {@code true}: 删除失败<br>{@code false}: 删除成功
     */
    public boolean deleteDir(File fileDir) {
        if (fileDir == null || !fileDir.exists() || !fileDir.isDirectory()) {
            return true;
        }
        boolean isSuccess = true;
        File[] files = fileDir.listFiles();
        for (int i = 0; i < files.length; i++) {
            // 如果遍历到的是文件,则删除文件
            if (files[i].isFile()) {
                isSuccess = deleteFile(files[i]);
                if (!isSuccess) break;
            }
            // 如果遍历到的是文件夹,则调用删除文件夹方法,递归
            else if (files[i].isDirectory()) {
                isSuccess = deleteDir(files[i]);
                if (!isSuccess) break;
            }
        }
        if (!isSuccess) return false;
        return fileDir.delete();
    }

    /***********************************************************************************************
     ****  获取文件或者文件夹的大小
     **********************************************************************************************/

    /**
     * 获取指定文件或者文件夹的大小
     *
     * @param path 文件或文件夹的路径
     * @return 文件或文件夹的字节数
     */
    public long getFileSize(String path) {
        return TextUtils.isEmpty(path) ? 0 : getFileSize(new File(path));
    }

    /**
     * 获取指定文件或者文件夹的大小
     *
     * @param file 文件或文件夹
     * @return 文件或文件夹的字节数
     */
    public long getFileSize(File file) {
        if (file == null) return 0;
        long size = 0;
        try {
            if (file.exists()) {
                if (file.isFile()) {
                    size += getSingleFileSize(file);
                } else {
                    size += getFileDirSize(file);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
            LogUtil.e(TAG, "Failed to get the specified file size ========> " + e.getMessage());
        }
        return size;
    }

    /**
     * 获取单个文件的大小
     *
     * @param path 文件的路径
     * @return 文件的字节数
     */
    public long getSingleFileSize(String path) {
        return TextUtils.isEmpty(path) ? 0 : getSingleFileSize(new File(path));
    }

    /**
     * 获取单个文件的大小
     *
     * @param file 文件
     * @return 文件的字节数
     * @throws Exception
     */
    public long getSingleFileSize(File file) {
        if (file == null) return 0;
        long size = 0;
        try {
            if (file.exists()) {
                FileInputStream fis = new FileInputStream(file);
                size = fis.available();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return size;
    }

    /**
     * 获取指定文件夹的大小
     *
     * @param dir 文件夹的路径
     * @return 文件夹的字节数
     */
    public long getFileDirSize(String dir) {
        return TextUtils.isEmpty(dir) ? 0 : getFileDirSize(new File(dir));
    }

    /**
     * 获取指定文件夹的大小
     *
     * @param dir 文件夹
     * @return 文件夹的字节数
     */
    public long getFileDirSize(File dir) {
        if (dir == null) return 0;
        long size = 0;
        File flist[] = dir.listFiles();
        for (int i = 0; i < flist.length; i++) {
            if (flist[i].isDirectory()) {
                size = size + getFileDirSize(flist[i]);
            } else {
                size = size + getSingleFileSize(flist[i]);
            }
        }
        return size;
    }

    /***********************************************************************************************
     ****  获取文件的真实路径
     **********************************************************************************************/

    /**
     * Get a file path from a Uri. This will get the the path for Storage Access
     * Framework Documents, as well as the _data field for the MediaStore and
     * other file-based ContentProviders.<br>
     * <br>
     * Callers should check whether the path is local before assuming it
     * represents a local file.
     *
     * @param uri The Uri to query.l
     */
    @TargetApi(Build.VERSION_CODES.KITKAT)
    public String getRealPath(@NonNull final Uri uri) {
        Context context = SUtils.getApp();
        final boolean isKitKat = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT;
        // DocumentProvider
        if (isKitKat && DocumentsContract.isDocumentUri(context, uri)) {
            // ExternalStorageProvider
            if (isExternalStorageDocument(uri)) {
                final String docId = DocumentsContract.getDocumentId(uri);
                final String[] split = docId.split(":");
                final String type = split[0];
                if ("primary".equalsIgnoreCase(type)) {
                    return Environment.getExternalStorageDirectory() + "/" + split[1];
                }
            }
            // DownloadsProvider
            else if (isDownloadsDocument(uri)) {
                final String id = DocumentsContract.getDocumentId(uri);
                final Uri contentUri = ContentUris.withAppendedId(
                        Uri.parse("content://downloads/public_downloads"), Long.valueOf(id));
                return getDataColumn(context, contentUri, null, null);
            }
            // MediaProvider
            else if (isMediaDocument(uri)) {
                final String docId = DocumentsContract.getDocumentId(uri);
                final String[] split = docId.split(":");
                final String type = split[0];

                Uri contentUri = null;
                if ("image".equals(type)) {
                    contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
                } else if ("video".equals(type)) {
                    contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
                } else if ("audio".equals(type)) {
                    contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
                }

                final String selection = "_id=?";
                final String[] selectionArgs = new String[]{split[1]};
                return getDataColumn(context, contentUri, selection, selectionArgs);
            }
        }
        // MediaStore (and general)
        else if ("content".equalsIgnoreCase(uri.getScheme())) {
            // Return the remote address
            if (isGooglePhotosUri(uri))
                return uri.getLastPathSegment();
            return getDataColumn(context, uri, null, null);
        }
        // File
        else if ("file".equalsIgnoreCase(uri.getScheme())) {
            return uri.getPath();
        }
        return null;
    }

    /**
     * @param uri The Uri to check.
     * @return Whether the Uri authority is ExternalStorageProvider.
     */
    public boolean isExternalStorageDocument(Uri uri) {
        return "com.android.externalstorage.documents".equals(uri.getAuthority());
    }

    /**
     * @param uri The Uri to check.
     * @return Whether the Uri authority is DownloadsProvider.
     */
    public boolean isDownloadsDocument(Uri uri) {
        return "com.android.providers.downloads.documents".equals(uri.getAuthority());
    }

    /**
     * @param uri The Uri to check.
     * @return Whether the Uri authority is MediaProvider.
     */
    public boolean isMediaDocument(Uri uri) {
        return "com.android.providers.media.documents".equals(uri.getAuthority());
    }

    /**
     * @param uri The Uri to check.
     * @return Whether the Uri authority is Google Photos.
     */
    public boolean isGooglePhotosUri(Uri uri) {
        return "com.google.android.apps.photos.content".equals(uri.getAuthority());
    }

    /**
     * Get the value of the data column for this Uri. This is useful for
     * MediaStore Uris, and other file-based ContentProviders.
     *
     * @param context       The context.
     * @param uri           The Uri to query.
     * @param selection     (Optional) Filter used in the query.
     * @param selectionArgs (Optional) Selection arguments used in the query.
     * @return The value of the _data column, which is typically a file path.
     */
    public String getDataColumn(@NonNull Context context, Uri uri, String selection, String[] selectionArgs) {
        Cursor cursor = null;
        final String column = "_data";
        final String[] projection = {column};
        try {
            cursor = context.getContentResolver().query(uri, projection, selection, selectionArgs, null);
            if (cursor != null && cursor.moveToFirst()) {
                final int column_index = cursor.getColumnIndexOrThrow(column);
                return cursor.getString(column_index);
            }
        } finally {
            if (cursor != null) {
                cursor.close();
            }
        }
        return null;
    }
}

猜你喜欢

转载自blog.csdn.net/weixin_34248849/article/details/87189414