package com.android.grape.util import android.os.Environment import android.util.Log import com.blankj.utilcode.util.LogUtils import java.io.BufferedInputStream import java.io.BufferedOutputStream import java.io.BufferedReader import java.io.BufferedWriter import java.io.File import java.io.FileInputStream import java.io.FileNotFoundException import java.io.FileOutputStream import java.io.FileWriter import java.io.IOException import java.io.InputStream import java.io.InputStreamReader import java.io.OutputStream import java.io.RandomAccessFile import java.io.UnsupportedEncodingException import java.nio.charset.StandardCharsets import java.util.Enumeration import java.util.zip.ZipEntry import java.util.zip.ZipFile /** * @author litianxiang * @description: * @date :2021/9/28 15:44 */ object FileUtils { private const val TAG = "IOSTQ:FileUtils" private const val BUFFER_SIZE = 1024 * 1024 //1M Byte //创建文件夹 fun createDir(destDirName: String): Boolean { var destDirName = destDirName val dir = File(destDirName) if (dir.exists()) { println("创建目录" + destDirName + "失败,目标目录已经存在") return false } if (!destDirName.endsWith(File.separator)) { destDirName = destDirName + File.separator } //创建目录 if (dir.mkdirs()) { Log.e("createDir", "创建目录" + destDirName + "成功!") return true } else { Log.e("createDir", "创建目录" + destDirName + "失败!") return false } } /** * 创建文件 * * @param filePath 文件地址 * @param fileName 文件名 * @return */ fun createFile(filePath: String, fileName: String): Boolean { val strFilePath = filePath + fileName val file = File(filePath) if (!file.exists()) { /** 注意这里是 mkdirs()方法 可以创建多个文件夹 */ file.mkdirs() } val subfile = File(strFilePath) if (!subfile.exists()) { try { val b = subfile.createNewFile() return b } catch (e: IOException) { e.printStackTrace() } } else { return true } return false } /** * 遍历文件夹下的文件 * * @param file 地址 */ fun getFile(file: File): List? { val list: MutableList = mutableListOf() val fileArray = file.listFiles() if (fileArray == null) { return null } else { for (f in fileArray) { if (f.isFile) { list.add(0, f) } else { getFile(f) } } } return list } /** * 删除文件 * * @param filePath 文件地址 * @return */ fun deleteFiles(filePath: String): Boolean { val files = getFile(File(filePath)) if (files!!.size != 0) { for (i in files.indices) { val file = files[i] /** 如果是文件则删除 如果都删除可不必判断 */ if (file.isFile) { file.delete() } } } return true } //删除文件夹和文件夹里面的文件 fun deleteDirWihtFile(dir: File?) { if (dir == null || !dir.exists() || !dir.isDirectory) return for (file in dir.listFiles()) { if (file.isFile) file.delete() // 删除所有文件 else if (file.isDirectory) deleteDirWihtFile(file) // 递规的方式删除文件夹 } dir.delete() // 删除目录本身 } /** * 向文件中添加内容 * * @param strcontent 内容 * @param filePath 地址 * @param fileName 文件名 */ fun writeToFile(strcontent: String, filePath: String, fileName: String) { //生成文件夹之后,再生成文件,不然会出错 val strFilePath = filePath + fileName // 每次写入时,都换行写 val subfile = File(strFilePath) var raf: RandomAccessFile? = null try { /** 构造函数 第二个是读写方式 */ raf = RandomAccessFile(subfile, "rw") /** 将记录指针移动到该文件的最后 */ raf.seek(subfile.length()) /** 向文件末尾追加内容 */ raf.write(strcontent.toByteArray()) raf.close() } catch (e: IOException) { e.printStackTrace() } } /** * 修改文件内容(覆盖或者添加) * * @param path 文件地址 * @param content 覆盖内容 * @param append 指定了写入的方式,是覆盖写还是追加写(true=追加)(false=覆盖) */ fun modifyFile(path: String?, content: String?, append: Boolean) { try { val fileWriter = FileWriter(path, append) val writer = BufferedWriter(fileWriter) writer.append(content) writer.flush() writer.close() } catch (e: IOException) { e.printStackTrace() } } /** * 读取文件内容 * * @param filePath 地址 * @param filename 名称 * @return 返回内容 */ fun getString(filePath: String, filename: String): String { var inputStream: FileInputStream? = null try { inputStream = FileInputStream(File(filePath + filename)) } catch (e: FileNotFoundException) { e.printStackTrace() } var inputStreamReader: InputStreamReader? = null try { inputStreamReader = InputStreamReader(inputStream, "UTF-8") } catch (e1: UnsupportedEncodingException) { e1.printStackTrace() } val reader = BufferedReader(inputStreamReader) val sb = StringBuffer("") var line: String? try { while ((reader.readLine().also { line = it }) != null) { sb.append(line) sb.append("\n") } } catch (e: IOException) { e.printStackTrace() } return sb.toString() } /** * 重命名文件 * * @param oldPath 原来的文件地址 * @param newPath 新的文件地址 */ fun renameFile(oldPath: String, newPath: String) { val oleFile = File(oldPath) val newFile = File(newPath) //执行重命名 oleFile.renameTo(newFile) } /** * 复制文件 * * @param fromFile 要复制的文件目录 * @param toFile 要粘贴的文件目录 * @return 是否复制成功 */ fun copy(fromFile: String, toFile: String): Boolean { //要复制的文件目录 val currentFiles: Array val root = File(fromFile) //如同判断SD卡是否存在或者文件是否存在 //如果不存在则 return出去 if (!root.exists()) { return false } //如果存在则获取当前目录下的全部文件 填充数组 currentFiles = root.listFiles() //目标目录 val targetDir = File(toFile) //创建目录 if (!targetDir.exists()) { targetDir.mkdirs() } //遍历要复制该目录下的全部文件 for (i in currentFiles.indices) { if (currentFiles[i].isDirectory) //如果当前项为子目录 进行递归 { copy(currentFiles[i].path + "/", toFile + currentFiles[i].name + "/") } else //如果当前项为文件则进行文件拷贝 { CopySdcardFile(currentFiles[i].path, toFile + currentFiles[i].name) } } return true } //文件拷贝 //要复制的目录下的所有非子目录(文件夹)文件拷贝 fun CopySdcardFile(fromFile: String?, toFile: String?): Boolean { try { val fosfrom: InputStream = FileInputStream(fromFile) val fosto: OutputStream = FileOutputStream(toFile) val bt = ByteArray(1024) var c: Int while ((fosfrom.read(bt).also { c = it }) > 0) { fosto.write(bt, 0, c) } fosfrom.close() fosto.close() return true } catch (ex: Exception) { return false } } /** * 获取目录下所有文件 * @param path 指定目录路径 * @return */ fun getFilesAllName(path: String): List? { val file = File(path) val files = file.listFiles() if (files == null) { Log.e("error", "空目录") return null } val s: MutableList = ArrayList() for (i in files.indices) { s.add(files[i].absolutePath) } return s } /** * 解压缩一个文件 * * @param zipFile 压缩文件 * @param folderPath 解压缩的目标目录 * @return * @throws IOException 当解压缩过程出错时抛出 */ @Throws(IOException::class) fun upZipFile(zipFile: File?, folderPath: String): ArrayList { val fileList = ArrayList() val desDir = File(folderPath) if (!desDir.exists()) { desDir.mkdirs() } val zf = ZipFile(zipFile) val entries: Enumeration<*> = zf.entries() while (entries.hasMoreElements()) { val entry = entries.nextElement() as ZipEntry if (entry.isDirectory) { continue } val `is` = zf.getInputStream(entry) var str = folderPath + File.separator + entry.name str = String(str.toByteArray(charset("8859_1")), charset("UTF-8")) val desFile = File(str) if (!desFile.exists()) { val fileParentDir = desFile.parentFile if (!fileParentDir!!.exists()) { fileParentDir.mkdirs() } desFile.createNewFile() } val os: OutputStream = FileOutputStream(desFile) val buffer = ByteArray(BUFFER_SIZE) var length: Int while ((`is`.read(buffer).also { length = it }) > 0) { os.write(buffer, 0, length) } os.flush() os.close() `is`.close() fileList.add(desFile) } return fileList } //复制文件 @Throws(IOException::class) fun copyFile(sourceFile: File?, targetFile: File?) { // 新建文件输入流并对它进行缓冲 val input = FileInputStream(sourceFile) val inBuff = BufferedInputStream(input) // 新建文件输出流并对它进行缓冲 val output = FileOutputStream(targetFile) val outBuff = BufferedOutputStream(output) // 缓冲数组 val b = ByteArray(1024 * 5) var len: Int while ((inBuff.read(b).also { len = it }) != -1) { outBuff.write(b, 0, len) } // 刷新此缓冲的输出流 outBuff.flush() //关闭流 inBuff.close() outBuff.close() output.close() input.close() } fun writePackageName(packageName: String) { val file = File( Environment.getExternalStorageDirectory(), "script/packagesname.txt" ) val parentDir = file.getParentFile() if (parentDir != null && !parentDir.exists()) { val dirsCreated = parentDir.mkdirs() if (!dirsCreated) { Log.e("FileWrite", "Failed to create directories: $parentDir") return } } LogUtils.d("TAG", "writePackageName: $packageName", null) try { BufferedOutputStream( FileOutputStream(file) ).use { bos -> bos.write(packageName.toByteArray(StandardCharsets.UTF_8)) bos.flush() // 确保数据写入磁盘 } } catch (e: IOException) { Log.e("FileWrite", "Failed to write package name: $packageName", e) // 6. 可以考虑添加重试机制或通知用户 } } }