文件操作小抄——来自IoUtils

202 阅读3分钟

通常Java的文件操作是编程语言中最复杂的之一,所以我们有必要自己简单封装一下文件的一些操作,如文件(夹)创建、复制、删除、移动、重命名,文件读写,计算文件夹大小,以及路径处理。

创建文件夹

fun createFolder(dirs: Array<String>) {
    for (dir in dirs) {
        createFolder(dir)
    }
}

fun createFolder(dir: String) {
    if (dir != "") {
        val folder = File(dir)
        if (!folder.exists()) {
            folder.mkdirs()
        }
    }
}

文件复制


private fun copyFile(file: File, dstDir: String): Boolean {
    val dstFolder = File(dstDir)
    if (!dstFolder.exists() || !file.isFile || !dstFolder.isDirectory) {
        return false
    }
    try {
        val inStream: InputStream = FileInputStream(file)
        val outStream: OutputStream = BufferedOutputStream(
            FileOutputStream(File(dstFolder, file.name))
        )
        var len: Int
        val buf = ByteArray(1024)
        while (inStream.read(buf).also { len = it } != -1) {
            outStream.write(buf, 0, len)
        }
        outStream.flush()
        if (outStream != null) {
            outStream.close()
        }
        if (inStream != null) {
            inStream.close()
        }
    } catch (e: FileNotFoundException) {
        e.printStackTrace()
        return false
    } catch (e: IOException) {
        e.printStackTrace()
        return false
    }
    return true
}

private fun copyFolder(file: File, dstDir: String): Boolean {
    val dstFolder = File(dstDir)
    if (!dstFolder.exists() || !file.isDirectory || !dstFolder.isDirectory) {
        return false
    }
    if (file.list() != null) {
        val children = file.list()
        for (i in children.indices) {
            val newDirFile = File(dstDir + File.separator + file.name)
            if (!newDirFile.exists()) {
                newDirFile.mkdir()
            }
            copy(File(file, children[i]), dstDir + File.separator + file.name)
        }
    }
    return true
}

fun copy(file: File, dstDir: String): Boolean {
    val dstFolder = File(dstDir)
    if (!dstFolder.exists() || !dstFolder.isDirectory) {
        return false
    }
    return if (file.isFile) {
        copyFile(file, dstDir)
    } else {
        copyFolder(file, dstDir)
    }
}

文件删除


private fun deleteFile(file: File): Boolean {
    return file.isFile && file.delete()
}

private fun deleteFolder(file: File): Boolean {
    return if (!file.isDirectory) {
        false
    } else {
        if (file.list() != null) {
            val children = file.list()
            for (i in children.indices) {
                delete(File(file, children[i]))
            }
        }
        file.delete()
    }
}

fun delete(file: File): Boolean {
    return if (file.isFile) {
        deleteFile(file)
    } else {
        deleteFolder(file)
    }
}

文件移动


private fun moveFile(file: File, dstDir: String): Boolean {
    val dstFolder = File(dstDir)
    return if (!file.isFile || !dstFolder.exists() || !dstFolder.isDirectory) {
        false
    } else {
        copyFile(file, dstDir)
        deleteFile(file)
        true
    }
}

private fun moveFolder(file: File, dstDir: String): Boolean {
    val dstFolder = File(dstDir)
    return file.isDirectory || !dstFolder.exists() || (!dstFolder.isDirectory
            && copyFolder(file, dstDir) && deleteFolder(file))
}

fun move(file: File, dstDir: String): Boolean {
    val dstFolder = File(dstDir)
    if (!dstFolder.exists() || !dstFolder.isDirectory) {
        return false
    }
    return if (file.isFile) {
        moveFile(file, dstDir)
    } else {
        copyFolder(file, dstDir) && delete(file)
    }
}

文件重命名


private fun renameFile(file: File, name: String): Boolean {
    return if (!file.isFile) {
        false
    } else {
        file.renameTo(File(file.parent, name))
    }
}

private fun renameFolder(file: File, name: String): Boolean {
    return if (!file.isDirectory) {
        false
    } else {
        val parent = file.parent
        file.renameTo(File(parent, name))
    }
}

fun rename(file: File, name: String): Boolean {
    return if (file.isFile) {
        renameFile(file, name)
    } else {
        renameFolder(file, name)
    }
}

读取二进制文件

fun read(file: File): ByteArray {
    val buffers = ByteArray(1024)
    val baos = ByteArrayOutputStream()
    val `is` = FileInputStream(file)
    var len: Int
    while (`is`.read(buffers).also { len = it } > 0) {
        baos.write(buffers, 0, len)
    }
    val fileBytes = baos.toByteArray()
    baos.close()
    `is`.close()
    return fileBytes
}

读取文本文件


fun readText(file: File): String {
    val `is` = FileInputStream(file)
    val baos = ByteArrayOutputStream()
    val buffer = ByteArray(1024 * 4)
    var len: Int
    while (`is`.read(buffer).also { len = it } != -1) {
        baos.write(buffer, 0, len)
    }
    val data = baos.toByteArray()
    return String(data)
}

fun readText(filePath: String): String {
    return readText(File(filePath))
}

写文件

fun write(bytes: ByteArray, filePath: String) {
    var fos: FileOutputStream? = null
    try {
        val file = File(filePath)
        if (!file.parentFile.exists()) {
            file.parentFile.mkdirs()
        }
        fos = FileOutputStream(file)
        fos.write(bytes)
        fos.flush()
    } finally {
        close(fos)
    }
}

fun write(inputStream: InputStream, filePath: String): File {
    var outputStream: OutputStream? = null
    val file = File(filePath)
    if (!file.parentFile.exists()) {
        file.parentFile.mkdirs()
    }
    try {
        outputStream = FileOutputStream(file)
        val buffer = ByteArray(4 * 1024)
        var lenght = 0
        while (inputStream.read(buffer).also { lenght = it } > 0) {
            outputStream.write(buffer, 0, lenght)
        }
        outputStream.flush()
    } catch (e: IOException) {
        e.printStackTrace()
    } finally {
        close(inputStream)
        close(outputStream)
    }
    return file
}

fun close(vararg closeableList: Closeable?) {
    try {
        for (closeable in closeableList) {
            closeable?.close()
        }
    } catch (ignore: IOException) {
    }
}

计算文件夹大小

fun formatFileSize(size: Double): String {
    val kiloByte = size / 1024
    if (kiloByte < 1 && size > 0) {
        return size.toString() + "B"
    } else if (size <= 0) {
        return "0B"
    }
    val megaByte = kiloByte / 1024
    if (megaByte < 1) {
        val result1 = BigDecimal(kiloByte.toString())
        return result1.setScale(2, BigDecimal.ROUND_HALF_UP)
            .toPlainString() + "KB"
    }
    val gigaByte = megaByte / 1024
    if (gigaByte < 1) {
        val result2 = BigDecimal(megaByte.toString())
        return result2.setScale(2, BigDecimal.ROUND_HALF_UP)
            .toPlainString() + "MB"
    }
    val teraBytes = gigaByte / 1024
    if (teraBytes < 1) {
        val result3 = BigDecimal(gigaByte.toString())
        return result3.setScale(2, BigDecimal.ROUND_HALF_UP)
            .toPlainString() + "GB"
    }
    val result4 = BigDecimal(teraBytes)
    return (result4.setScale(2, BigDecimal.ROUND_HALF_UP).toPlainString()
            + "TB")
}

fun getFolderTotalSize(file: File): Long {
    var size: Long = 0
    try {
        val files = file.listFiles()
        val subCount: Int
        if (files != null) {
            subCount = files.size
            for (i in 0 until subCount) {
                size = if (files[i].isDirectory) {
                    size + getFolderTotalSize(files[i])
                } else {
                    size + files[i].length()
                }
            }
        }
    } catch (e: Exception) {
        e.printStackTrace()
    }
    return size
}

fun getSubFilesCount(folder: File): Int {
    return if (!folder.isDirectory) {
        -1
    } else {
        folder.list().size
    }
}

路径处理

fun getParentPath(path: String): String {
    var path = path
    if (path.endsWith(File.separator)) {
        path = path.substring(0, path.length - 1)
    }
    val start = path.lastIndexOf(File.separator)
    return path.substring(0, start)
}

fun getFileNameFromPath(path: String): String {
    return getFileNameFromPath(path, true)
}

fun getNameFromPath(path: String): String {
    return getFileNameFromPath(path, false)
}

private fun getFileNameFromPath(path: String, withSuffix: Boolean): String {
    val start = path.lastIndexOf(File.separator) + 1
    val end = path.lastIndexOf(".")
    return if (withSuffix) {
        path.substring(start)
    } else {
        path.substring(start, end)
    }
}