import android.annotation.SuppressLint; | |
import com.blankj.utilcode.constant.MemoryConstants; | |
import java.io.BufferedInputStream; | |
import java.io.BufferedOutputStream; | |
import java.io.BufferedReader; | |
import java.io.BufferedWriter; | |
import java.io.ByteArrayOutputStream; | |
import java.io.File; | |
import java.io.FileInputStream; | |
import java.io.FileNotFoundException; | |
import java.io.FileOutputStream; | |
import java.io.FileReader; | |
import java.io.FileWriter; | |
import java.io.FilenameFilter; | |
import java.io.IOException; | |
import java.io.InputStream; | |
import java.io.InputStreamReader; | |
import java.io.OutputStream; | |
import java.security.DigestInputStream; | |
import java.security.MessageDigest; | |
import java.security.NoSuchAlgorithmException; | |
import java.util.ArrayList; | |
import java.util.Collections; | |
import java.util.List; | |
/** | |
* <pre> | |
* author: Blankj | |
* blog : http://blankj.com | |
* time : 2016/8/11 | |
* desc : 文件相关工具类 | |
* </pre> | |
*/ | |
public final class FileUtils { | |
private FileUtils() { | |
throw new UnsupportedOperationException("u can't instantiate me..."); | |
} | |
/** | |
* 根据文件路径获取文件 | |
* | |
* @param filePath 文件路径 | |
* @return 文件 | |
*/ | |
public static File getFileByPath(StringfilePath) { | |
return isSpace(filePath) ? null : new File(filePath); | |
} | |
/** | |
* 判断文件是否存在 | |
* | |
* @param filePath 文件路径 | |
* @return {@code true}: 存在<br>{@code false}: 不存在 | |
*/ | |
public static boolean isFileExists(StringfilePath) { | |
return isFileExists(getFileByPath(filePath)); | |
} | |
/** | |
* 判断文件是否存在 | |
* | |
* @param file 文件 | |
* @return {@code true}: 存在<br>{@code false}: 不存在 | |
*/ | |
public static boolean isFileExists(File file) { | |
return file != null && file.exists(); | |
} | |
/** | |
* 重命名文件 | |
* | |
* @param filePath 文件路径 | |
* @param newName 新名称 | |
* @return {@code true}: 重命名成功<br>{@code false}: 重命名失败 | |
*/ | |
public static boolean rename(String filePath, String newName) { | |
return rename(getFileByPath(filePath), newName); | |
} | |
/** | |
* 重命名文件 | |
* | |
* @param file 文件 | |
* @param newName 新名称 | |
* @return {@code true}: 重命名成功<br>{@code false}: 重命名失败 | |
*/ | |
public static boolean rename(File file, String newName) { | |
// 文件为空返回false | |
if (file == null) return false; | |
// 文件不存在返回false | |
if (!file.exists())return false; | |
// 新的文件名为空返回false | |
if (isSpace(newName)) return false; | |
// 如果文件名没有改变返回true | |
if (newName.equals(file.getName()))return true; | |
File newFile = new File(file.getParent()+ File.separator + newName); | |
// 如果重命名的文件已存在返回false | |
return !newFile.exists() | |
&& file.renameTo(newFile); | |
} | |
/** | |
* 判断是否是目录 | |
* | |
* @param dirPath 目录路径 | |
* @return {@code true}: 是<br>{@code false}: 否 | |
*/ | |
public static boolean isDir(String dirPath) { | |
return isDir(getFileByPath(dirPath)); | |
} | |
/** | |
* 判断是否是目录 | |
* | |
* @param file 文件 | |
* @return {@code true}: 是<br>{@code false}: 否 | |
*/ | |
public static boolean isDir(File file) { | |
return isFileExists(file) && file.isDirectory(); | |
} | |
/** | |
* 判断是否是文件 | |
* | |
* @param filePath 文件路径 | |
* @return {@code true}: 是<br>{@code false}: 否 | |
*/ | |
public static boolean isFile(String filePath) { | |
return isFile(getFileByPath(filePath)); | |
} | |
/** | |
* 判断是否是文件 | |
* | |
* @param file 文件 | |
* @return {@code true}: 是<br>{@code false}: 否 | |
*/ | |
public static boolean isFile(File file) { | |
return isFileExists(file) && file.isFile(); | |
} | |
/** | |
* 判断目录是否存在,不存在则判断是否创建成功 | |
* | |
* @param dirPath 目录路径 | |
* @return {@code true}: 存在或创建成功<br>{@code false}: 不存在或创建失败 | |
*/ | |
public static boolean createOrExistsDir(StringdirPath) { | |
return createOrExistsDir(getFileByPath(dirPath)); | |
} | |
/** | |
* 判断目录是否存在,不存在则判断是否创建成功 | |
* | |
* @param file 文件 | |
* @return {@code true}: 存在或创建成功<br>{@code false}: 不存在或创建失败 | |
*/ | |
public static boolean createOrExistsDir(Filefile) { | |
// 如果存在,是目录则返回true,是文件则返回false,不存在则返回是否创建成功 | |
return file != null && (file.exists() ? file.isDirectory(): file.mkdirs()); | |
} | |
/** | |
* 判断文件是否存在,不存在则判断是否创建成功 | |
* | |
* @param filePath 文件路径 | |
* @return {@code true}: 存在或创建成功<br>{@code false}: 不存在或创建失败 | |
*/ | |
public static boolean createOrExistsFile(StringfilePath) { | |
return createOrExistsFile(getFileByPath(filePath)); | |
} | |
/** | |
* 判断文件是否存在,不存在则判断是否创建成功 | |
* | |
* @param file 文件 | |
* @return {@code true}: 存在或创建成功<br>{@code false}: 不存在或创建失败 | |
*/ | |
public static boolean createOrExistsFile(Filefile) { | |
if (file == null) return false; | |
// 如果存在,是文件则返回true,是目录则返回false | |
if (file.exists())return file.isFile(); | |
if (!createOrExistsDir(file.getParentFile()))return false; | |
try { | |
return file.createNewFile(); | |
} catch (IOException e) { | |
e.printStackTrace(); | |
return false; | |
} | |
} | |
/** | |
* 判断文件是否存在,存在则在创建之前删除 | |
* | |
* @param filePath 文件路径 | |
* @return {@code true}: 创建成功<br>{@code false}: 创建失败 | |
*/ | |
public static boolean createFileByDeleteOldFile(StringfilePath) { | |
return createFileByDeleteOldFile(getFileByPath(filePath)); | |
} | |
/** | |
* 判断文件是否存在,存在则在创建之前删除 | |
* | |
* @param file 文件 | |
* @return {@code true}: 创建成功<br>{@code false}: 创建失败 | |
*/ | |
public static boolean createFileByDeleteOldFile(Filefile) { | |
if (file == null) return false; | |
// 文件存在并且删除失败返回false | |
if (file.exists()&& file.isFile()&& !file.delete()) return false; | |
// 创建目录失败返回false | |
if (!createOrExistsDir(file.getParentFile()))return false; | |
try { | |
return file.createNewFile(); | |
} catch (IOException e) { | |
e.printStackTrace(); | |
return false; | |
} | |
} | |
/** | |
* 复制或移动目录 | |
* | |
* @param srcDirPath 源目录路径 | |
* @param destDirPath 目标目录路径 | |
* @param isMove 是否移动 | |
* @return {@code true}: 复制或移动成功<br>{@code false}: 复制或移动失败 | |
*/ | |
private static boolean copyOrMoveDir(StringsrcDirPath, String destDirPath,boolean isMove) { | |
return copyOrMoveDir(getFileByPath(srcDirPath), getFileByPath(destDirPath), isMove); | |
} | |
/** | |
* 复制或移动目录 | |
* | |
* @param srcDir 源目录 | |
* @param destDir 目标目录 | |
* @param isMove 是否移动 | |
* @return {@code true}: 复制或移动成功<br>{@code false}: 复制或移动失败 | |
*/ | |
private static boolean copyOrMoveDir(FilesrcDir, File destDir, boolean isMove) { | |
if (srcDir == null || destDir == null) return false; | |
// 如果目标目录在源目录中则返回false,看不懂的话好好想想递归怎么结束 | |
// srcPath : F:\\MyGithub\\AndroidUtilCode\\utilcode\\src\\test\\res | |
// destPath: F:\\MyGithub\\AndroidUtilCode\\utilcode\\src\\test\\res1 | |
// 为防止以上这种情况出现出现误判,须分别在后面加个路径分隔符 | |
String srcPath = srcDir.getPath() + File.separator; | |
String destPath = destDir.getPath()+ File.separator; | |
if (destPath.contains(srcPath))return false; | |
// 源文件不存在或者不是目录则返回false | |
if (!srcDir.exists()|| !srcDir.isDirectory())return false; | |
// 目标目录不存在返回false | |
if (!createOrExistsDir(destDir))return false; | |
File[] files = srcDir.listFiles(); | |
for (File file: files) { | |
File oneDestFile = new File(destPath + file.getName()); | |
if (file.isFile()) { | |
// 如果操作失败返回false | |
if (!copyOrMoveFile(file, oneDestFile, isMove))return false; | |
} else if (file.isDirectory()) { | |
// 如果操作失败返回false | |
if (!copyOrMoveDir(file, oneDestFile, isMove))return false; | |
} | |
} | |
return !isMove || deleteDir(srcDir); | |
} | |
/** | |
* 复制或移动文件 | |
* | |
* @param srcFilePath 源文件路径 | |
* @param destFilePath 目标文件路径 | |
* @param isMove 是否移动 | |
* @return {@code true}: 复制或移动成功<br>{@code false}: 复制或移动失败 | |
*/ | |
private static boolean copyOrMoveFile(StringsrcFilePath, String destFilePath,boolean isMove) { | |
return copyOrMoveFile(getFileByPath(srcFilePath), getFileByPath(destFilePath), isMove); | |
} | |
/** | |
* 复制或移动文件 | |
* | |
* @param srcFile 源文件 | |
* @param destFile 目标文件 | |
* @param isMove 是否移动 | |
* @return {@code true}: 复制或移动成功<br>{@code false}: 复制或移动失败 | |
*/ | |
private static boolean copyOrMoveFile(FilesrcFile, File destFile, boolean isMove) { | |
if (srcFile == null || destFile == null) return false; | |
// 源文件不存在或者不是文件则返回false | |
if (!srcFile.exists()|| !srcFile.isFile()) return false; | |
// 目标文件存在且是文件则返回false | |
if (destFile.exists()&& destFile.isFile())return false; | |
// 目标目录不存在返回false | |
if (!createOrExistsDir(destFile.getParentFile()))return false; | |
try { | |
return writeFileFromIS(destFile,new FileInputStream(srcFile), false) | |
&& !(isMove && !deleteFile(srcFile)); | |
} catch (FileNotFoundException e) { | |
e.printStackTrace(); | |
return false; | |
} | |
} | |
/** | |
* 复制目录 | |
* | |
* @param srcDirPath 源目录路径 | |
* @param destDirPath 目标目录路径 | |
* @return {@code true}: 复制成功<br>{@code false}: 复制失败 | |
*/ | |
public static boolean copyDir(String srcDirPath, StringdestDirPath) { | |
return copyDir(getFileByPath(srcDirPath), getFileByPath(destDirPath)); | |
} | |
/** | |
* 复制目录 | |
* | |
* @param srcDir 源目录 | |
* @param destDir 目标目录 | |
* @return {@code true}: 复制成功<br>{@code false}: 复制失败 | |
*/ | |
public static boolean copyDir(File srcDir, File destDir) { | |
return copyOrMoveDir(srcDir, destDir,false); | |
} | |
/** | |
* 复制文件 | |
* | |
* @param srcFilePath 源文件路径 | |
* @param destFilePath 目标文件路径 | |
* @return {@code true}: 复制成功<br>{@code false}: 复制失败 | |
*/ | |
public static boolean copyFile(String srcFilePath, StringdestFilePath) { | |
return copyFile(getFileByPath(srcFilePath), getFileByPath(destFilePath)); | |
} | |
/** | |
* 复制文件 | |
* | |
* @param srcFile 源文件 | |
* @param destFile 目标文件 | |
* @return {@code true}: 复制成功<br>{@code false}: 复制失败 | |
*/ | |
public static boolean copyFile(File srcFile, File destFile) { | |
return copyOrMoveFile(srcFile, destFile,false); | |
} | |
/** | |
* 移动目录 | |
* | |
* @param srcDirPath 源目录路径 | |
* @param destDirPath 目标目录路径 | |
* @return {@code true}: 移动成功<br>{@code false}: 移动失败 | |
*/ | |
public static boolean moveDir(String srcDirPath, StringdestDirPath) { | |
return moveDir(getFileByPath(srcDirPath), getFileByPath(destDirPath)); | |
} | |
/** | |
* 移动目录 | |
* | |
* @param srcDir 源目录 | |
* @param destDir 目标目录 | |
* @return {@code true}: 移动成功<br>{@code false}: 移动失败 | |
*/ | |
public static boolean moveDir(File srcDir, File destDir) { | |
return copyOrMoveDir(srcDir, destDir,true); | |
} | |
/** | |
* 移动文件 | |
* | |
* @param srcFilePath 源文件路径 | |
* @param destFilePath 目标文件路径 | |
* @return {@code true}: 移动成功<br>{@code false}: 移动失败 | |
*/ | |
public static boolean moveFile(String srcFilePath, StringdestFilePath) { | |
return moveFile(getFileByPath(srcFilePath), getFileByPath(destFilePath)); | |
} | |
/** | |
* 移动文件 | |
* | |
* @param srcFile 源文件 | |
* @param destFile 目标文件 | |
* @return {@code true}: 移动成功<br>{@code false}: 移动失败 | |
*/ | |
public static boolean moveFile(File srcFile, File destFile) { | |
return copyOrMoveFile(srcFile, destFile,true); | |
} | |
/** | |
* 删除目录 | |
* | |
* @param dirPath 目录路径 | |
* @return {@code true}: 删除成功<br>{@code false}: 删除失败 | |
*/ | |
public static boolean deleteDir(String dirPath) { | |
return deleteDir(getFileByPath(dirPath)); | |
} | |
/** | |
* 删除目录 | |
* | |
* @param dir 目录 | |
* @return {@code true}: 删除成功<br>{@code false}: 删除失败 | |
*/ | |
public static boolean deleteDir(File dir) { | |
if (dir == null) return false; | |
// 目录不存在返回true | |
if (!dir.exists())return true; | |
// 不是目录返回false | |
if (!dir.isDirectory())return false; | |
// 现在文件存在且是文件夹 | |
File[] files = dir.listFiles(); | |
if (files != null && files.length != 0) { | |
for (File file: files) { | |
if (file.isFile()) { | |
if (!deleteFile(file))return false; | |
} else if (file.isDirectory()) { | |
if (!deleteDir(file))return false; | |
} | |
} | |
} | |
return dir.delete(); | |
} | |
/** | |
* 删除文件 | |
* | |
* @param srcFilePath 文件路径 | |
* @return {@code true}: 删除成功<br>{@code false}: 删除失败 | |
*/ | |
public static boolean deleteFile(String srcFilePath) { | |
return deleteFile(getFileByPath(srcFilePath)); | |
} | |
/** | |
* 删除文件 | |
* | |
* @param file 文件 | |
* @return {@code true}: 删除成功<br>{@code false}: 删除失败 | |
*/ | |
public static boolean deleteFile(File file) { | |
return file != null && (!file.exists()|| file.isFile()&& file.delete()); | |
} | |
/** | |
* 删除目录下的所有文件 | |
* | |
* @param dirPath 目录路径 | |
* @return {@code true}: 删除成功<br>{@code false}: 删除失败 | |
*/ | |
public static boolean deleteFilesInDir(StringdirPath) { | |
return deleteFilesInDir(getFileByPath(dirPath)); | |
} | |
/** | |
* 删除目录下的所有文件 | |
* | |
* @param dir 目录 | |
* @return {@code true}: 删除成功<br>{@code false}: 删除失败 | |
*/ | |
public static boolean deleteFilesInDir(Filedir) { | |
if (dir == null) return false; | |
// 目录不存在返回true | |
if (!dir.exists())return true; | |
// 不是目录返回false | |
if (!dir.isDirectory())return false; | |
// 现在文件存在且是文件夹 | |
File[] files = dir.listFiles(); | |
if (files != null && files.length != 0) { | |
for (File file: files) { | |
if (file.isFile()) { | |
if (!deleteFile(file))return false; | |
} else if (file.isDirectory()) { | |
if (!deleteDir(file))return false; | |
} | |
} | |
} | |
return true; | |
} | |
/** | |
* 获取目录下所有文件 | |
* | |
* @param dirPath 目录路径 | |
* @param isRecursive 是否递归进子目录 | |
* @return 文件链表 | |
*/ | |
public static List<File>listFilesInDir(StringdirPath, boolean isRecursive) { | |
return listFilesInDir(getFileByPath(dirPath), isRecursive); | |
} | |
/** | |
* 获取目录下所有文件 | |
* | |
* @param dir 目录 | |
* @param isRecursive 是否递归进子目录 | |
* @return 文件链表 | |
*/ | |
public static List<File>listFilesInDir(Filedir, boolean isRecursive) { | |
if (!isDir(dir))return null; | |
if (isRecursive) return listFilesInDir(dir); | |
List<File> list= new ArrayList<>(); | |
File[] files = dir.listFiles(); | |
if (files != null && files.length != 0) { | |
Collections.addAll(list, files); | |
} | |
return list; | |
} | |
/** | |
* 获取目录下所有文件包括子目录 | |
* | |
* @param dirPath 目录路径 | |
* @return 文件链表 | |
*/ | |
public static List<File>listFilesInDir(StringdirPath) { | |
return listFilesInDir(getFileByPath(dirPath)); | |
} | |
/** | |
* 获取目录下所有文件包括子目录 | |
* | |
* @param dir 目录 | |
* @return 文件链表 | |
*/ | |
public static List<File>listFilesInDir(Filedir) { | |
if (!isDir(dir))return null; | |
List<File> list= new ArrayList<>(); | |
File[] files = dir.listFiles(); | |
if (files != null && files.length != 0) { | |
for (File file: files) { | |
list.add(file); | |
if (file.isDirectory()) { | |
list.addAll(listFilesInDir(file)); | |
} | |
} | |
} | |
return list; | |
} | |
/** | |
* 获取目录下所有后缀名为suffix的文件 | |
* <p>大小写忽略</p> | |
* | |
* @param dirPath 目录路径 | |
* @param suffix 后缀名 | |
* @param isRecursive 是否递归进子目录 | |
* @return 文件链表 | |
*/ | |
public static List<File>listFilesInDirWithFilter(StringdirPath, String suffix, boolean isRecursive) { | |
return listFilesInDirWithFilter(getFileByPath(dirPath), suffix, isRecursive); | |
} | |
/** | |
* 获取目录下所有后缀名为suffix的文件 | |
* <p>大小写忽略</p> | |
* | |
* @param dir 目录 | |
* @param suffix 后缀名 | |
* @param isRecursive 是否递归进子目录 | |
* @return 文件链表 | |
*/ | |
public static List<File>listFilesInDirWithFilter(Filedir, String suffix, boolean isRecursive) { | |
if (isRecursive) return listFilesInDirWithFilter(dir, suffix); | |
if (dir == null || !isDir(dir)) return null; | |
List<File> list= new ArrayList<>(); | |
File[] files = dir.listFiles(); | |
if (files != null && files.length != 0) { | |
for (File file: files) { | |
if (file.getName().toUpperCase().endsWith(suffix.toUpperCase())) { | |
list.add(file); | |
} | |
} | |
} | |
return list; | |
} | |
/** | |
* 获取目录下所有后缀名为suffix的文件包括子目录 | |
* <p>大小写忽略</p> | |
* | |
* @param dirPath 目录路径 | |
* @param suffix 后缀名 | |
* @return 文件链表 | |
*/ | |
public static List<File>listFilesInDirWithFilter(StringdirPath, String suffix) { | |
return listFilesInDirWithFilter(getFileByPath(dirPath), suffix); | |
} | |
/** | |
* 获取目录下所有后缀名为suffix的文件包括子目录 | |
* <p>大小写忽略</p> | |
* | |
* @param dir 目录 | |
* @param suffix 后缀名 | |
* @return 文件链表 | |
*/ | |
public static List<File>listFilesInDirWithFilter(Filedir, String suffix) { | |
if (dir == null || !isDir(dir)) return null; | |
List<File> list= new ArrayList<>(); | |
File[] files = dir.listFiles(); | |
if (files != null && files.length != 0) { | |
for (File file: files) { | |
if (file.getName().toUpperCase().endsWith(suffix.toUpperCase())) { | |
list.add(file); | |
} | |
if (file.isDirectory()) { | |
list.addAll(listFilesInDirWithFilter(file, suffix)); | |
} | |
} | |
} | |
return list; | |
} | |
/** | |
* 获取目录下所有符合filter的文件 | |
* | |
* @param dirPath 目录路径 | |
* @param filter 过滤器 | |
* @param isRecursive 是否递归进子目录 | |
* @return 文件链表 | |
*/ | |
public static List<File>listFilesInDirWithFilter(StringdirPath, FilenameFilter filter,boolean isRecursive) { | |
return listFilesInDirWithFilter(getFileByPath(dirPath), filter, isRecursive); | |
} | |
/** | |
* 获取目录下所有符合filter的文件 | |
* | |
* @param dir 目录 | |
* @param filter 过滤器 | |
* @param isRecursive 是否递归进子目录 | |
* @return 文件链表 | |
*/ | |
public static List<File>listFilesInDirWithFilter(Filedir, FilenameFilter filter,boolean isRecursive) { | |
if (isRecursive) return listFilesInDirWithFilter(dir, filter); | |
if (dir == null || !isDir(dir)) return null; | |
List<File> list= new ArrayList<>(); | |
File[] files = dir.listFiles(); | |
if (files != null && files.length != 0) { | |
for (File file: files) { | |
if (filter.accept(file.getParentFile(), file.getName())) { | |
list.add(file); | |
} | |
} | |
} | |
return list; | |
} | |
/** | |
* 获取目录下所有符合filter的文件包括子目录 | |
* | |
* @param dirPath 目录路径 | |
* @param filter 过滤器 | |
* @return 文件链表 | |
*/ | |
public static List<File>listFilesInDirWithFilter(StringdirPath, FilenameFilter filter) { | |
return listFilesInDirWithFilter(getFileByPath(dirPath), filter); | |
} | |
/** | |
* 获取目录下所有符合filter的文件包括子目录 | |
* | |
* @param dir 目录 | |
* @param filter 过滤器 | |
* @return 文件链表 | |
*/ | |
public static List<File>listFilesInDirWithFilter(Filedir, FilenameFilter filter) { | |
if (dir == null || !isDir(dir)) return null; | |
List<File> list= new ArrayList<>(); | |
File[] files = dir.listFiles(); | |
if (files != null && files.length != 0) { | |
for (File file: files) { | |
if (filter.accept(file.getParentFile(), file.getName())) { | |
list.add(file); | |
} | |
if (file.isDirectory()) { | |
list.addAll(listFilesInDirWithFilter(file, filter)); | |
} | |
} | |
} | |
return list; | |
} | |
/** | |
* 获取目录下指定文件名的文件包括子目录 | |
* <p>大小写忽略</p> | |
* | |
* @param dirPath 目录路径 | |
* @param fileName 文件名 | |
* @return 文件链表 | |
*/ | |
public static List<File>searchFileInDir(StringdirPath, String fileName) { | |
return searchFileInDir(getFileByPath(dirPath), fileName); | |
} | |
/** | |
* 获取目录下指定文件名的文件包括子目录 | |
* <p>大小写忽略</p> | |
* | |
* @param dir 目录 | |
* @param fileName 文件名 | |
* @return 文件链表 | |
*/ | |
public static List<File>searchFileInDir(Filedir, String fileName) { | |
if (dir == null || !isDir(dir)) return null; | |
List<File> list= new ArrayList<>(); | |
File[] files = dir.listFiles(); | |
if (files != null && files.length != 0) { | |
for (File file: files) { | |
if (file.getName().toUpperCase().equals(fileName.toUpperCase())) { | |
list.add(file); | |
} | |
if (file.isDirectory()) { | |
list.addAll(searchFileInDir(file, fileName)); | |
} | |
} | |
} | |
return list; | |
} | |
/** | |
* 将输入流写入文件 | |
* | |
* @param filePath 路径 | |
* @param is 输入流 | |
* @param append 是否追加在文件末 | |
* @return {@code true}: 写入成功<br>{@code false}: 写入失败 | |
*/ | |
public static boolean writeFileFromIS(StringfilePath, InputStream is, boolean append) { | |
return writeFileFromIS(getFileByPath(filePath), is, append); | |
} | |
/** | |
* 将输入流写入文件 | |
* | |
* @param file 文件 | |
* @param is 输入流 | |
* @param append 是否追加在文件末 | |
* @return {@code true}: 写入成功<br>{@code false}: 写入失败 | |
*/ | |
public static boolean writeFileFromIS(Filefile, InputStream is, boolean append) { | |
if (file == null || is == null) return false; | |
if (!createOrExistsFile(file))return false; | |
OutputStream os = null; | |
try { | |
os = new BufferedOutputStream(newFileOutputStream(file, append)); | |
byte data[] = new byte[1024]; | |
int len; | |
while ((len = is.read(data, 0, 1024)) != -1) { | |
os.write(data, 0, len); | |
} | |
return true; | |
} catch (IOException e) { | |
e.printStackTrace(); | |
return false; | |
} finally { | |
CloseUtils.closeIO(is, os); | |
} | |
} | |
/** | |
* 将字符串写入文件 | |
* | |
* @param filePath 文件路径 | |
* @param content 写入内容 | |
* @param append 是否追加在文件末 | |
* @return {@code true}: 写入成功<br>{@code false}: 写入失败 | |
*/ | |
public static boolean writeFileFromString(StringfilePath, String content, boolean append) { | |
return writeFileFromString(getFileByPath(filePath), content, append); | |
} | |
/** | |
* 将字符串写入文件 | |
* | |
* @param file 文件 | |
* @param content 写入内容 | |
* @param append 是否追加在文件末 | |
* @return {@code true}: 写入成功<br>{@code false}: 写入失败 | |
*/ | |
public static boolean writeFileFromString(Filefile, String content, boolean append) { | |
if (file == null || content == null) return false; | |
if (!createOrExistsFile(file))return false; | |
BufferedWriter bw = null; | |
try { | |
bw = new BufferedWriter(newFileWriter(file, append)); | |
bw.write(content); | |
return true; | |
} catch (IOException e) { | |
e.printStackTrace(); | |
return false; | |
} finally { | |
CloseUtils.closeIO(bw); | |
} | |
} | |
/** | |
* 指定编码按行读取文件到链表中 | |
* | |
* @param filePath 文件路径 | |
* @param charsetName 编码格式 | |
* @return 文件行链表 | |
*/ | |
public static List<String>readFile2List(StringfilePath, String charsetName) { | |
return readFile2List(getFileByPath(filePath), charsetName); | |
} | |
/** | |
* 指定编码按行读取文件到链表中 | |
* | |
* @param file 文件 | |
* @param charsetName 编码格式 | |
* @return 文件行链表 | |
*/ | |
public static List<String>readFile2List(Filefile, String charsetName) { | |
return readFile2List(file,0, 0x7FFFFFFF, charsetName); | |
} | |
/** | |
* 指定编码按行读取文件到链表中 | |
* | |
* @param filePath 文件路径 | |
* @param st 需要读取的开始行数 | |
* @param end 需要读取的结束行数 | |
* @param charsetName 编码格式 | |
* @return 包含制定行的list | |
*/ | |
public static List<String>readFile2List(StringfilePath, int st, int end, String | |
charsetName) { | |
return readFile2List(getFileByPath(filePath), st, end, charsetName); | |
} | |
/** | |
* 指定编码按行读取文件到链表中 | |
* | |
* @param file 文件 | |
* @param st 需要读取的开始行数 | |
* @param end 需要读取的结束行数 | |
* @param charsetName 编码格式 | |
* @return 包含从start行到end行的list | |
*/ | |
public static List<String>readFile2List(Filefile, int st, int end, String charsetName) { | |
if (file == null) return null; | |
if (st > end) return null; | |
BufferedReader reader = null; | |
try { | |
String line; | |
int curLine = 1; | |
List<String> list= new ArrayList<>(); | |
if (isSpace(charsetName)) { | |
reader = new BufferedReader(newFileReader(file)); | |
} else { | |
reader = new BufferedReader(newInputStreamReader(newFileInputStream(file), charsetName)); | |
} | |
while ((line = reader.readLine())!= null) { | |
if (curLine > end) break; | |
if (st <= curLine && curLine<= end) list.add(line); | |
++curLine; | |
} | |
return list; | |
} catch (IOException e) { | |
e.printStackTrace(); | |
return null; | |
} finally { | |
CloseUtils.closeIO(reader); | |
} | |
} | |
/** | |
* 指定编码按行读取文件到字符串中 | |
* | |
* @param filePath 文件路径 | |
* @param charsetName 编码格式 | |
* @return 字符串 | |
*/ | |
public static String readFile2String(StringfilePath, String charsetName) { | |
return readFile2String(getFileByPath(filePath), charsetName); | |
} | |
/** | |
* 指定编码按行读取文件到字符串中 | |
* | |
* @param file 文件 | |
* @param charsetName 编码格式 | |
* @return 字符串 | |
*/ | |
public static String readFile2String(Filefile, String charsetName) { | |
if (file == null) return null; | |
BufferedReader reader = null; | |
try { | |
StringBuilder sb = new StringBuilder(); | |
if (isSpace(charsetName)) { | |
reader = new BufferedReader(newInputStreamReader(newFileInputStream(file))); | |
} else { | |
reader = new BufferedReader(newInputStreamReader(newFileInputStream(file), charsetName)); | |
} | |
String line; | |
while ((line = reader.readLine())!= null) { | |
sb.append(line).append("\r\n");// windows系统换行为\r\n,Linux为\n | |
} | |
// 要去除最后的换行符 | |
return sb.delete(sb.length()- 2, sb.length()).toString(); | |
} catch (IOException e) { | |
e.printStackTrace(); | |
return null; | |
} finally { | |
CloseUtils.closeIO(reader); | |
} | |
} | |
/** | |
* 读取文件到字符数组中 | |
* | |
* @param filePath 文件路径 | |
* @return 字符数组 | |
*/ | |
public static byte[] readFile2Bytes(StringfilePath) { | |
return readFile2Bytes(getFileByPath(filePath)); | |
} | |
/** | |
* 读取文件到字符数组中 | |
* | |
* @param file 文件 | |
* @return 字符数组 | |
*/ | |
public static byte[] readFile2Bytes(Filefile) { | |
if (file == null) return null; | |
try { | |
return inputStream2Bytes(newFileInputStream(file)); | |
} catch (FileNotFoundException e) { | |
e.printStackTrace(); | |
return null; | |
} | |
} | |
/** | |
* 获取文件最后修改的毫秒时间戳 | |
* | |
* @param filePath 文件路径 | |
* @return 文件最后修改的毫秒时间戳 | |
*/ | |
public static long getFileLastModified(StringfilePath) { | |
return getFileLastModified(getFileByPath(filePath)); | |
} | |
/** | |
* 获取文件最后修改的毫秒时间戳 | |
* | |
* @param file 文件 | |
* @return 文件最后修改的毫秒时间戳 | |
*/ | |
public static long getFileLastModified(Filefile) { | |
if (file == null) return -1; | |
return file.lastModified(); | |
} | |
/** | |
* 简单获取文件编码格式 | |
* | |
* @param filePath 文件路径 | |
* @return 文件编码 | |
*/ | |
public static String getFileCharsetSimple(StringfilePath) { | |
return getFileCharsetSimple(getFileByPath(filePath)); | |
} | |
/** | |
* 简单获取文件编码格式 | |
* | |
* @param file 文件 | |
* @return 文件编码 | |
*/ | |
public static String getFileCharsetSimple(Filefile) { | |
int p = 0; | |
InputStream is = null; | |
try { | |
is = new BufferedInputStream(newFileInputStream(file)); | |
p = (is.read()<< 8) + is.read(); | |
} catch (IOException e) { | |
e.printStackTrace(); | |
} finally { | |
CloseUtils.closeIO(is); | |
} | |
switch (p) { | |
case 0xefbb: | |
return "UTF-8"; | |
case 0xfffe: | |
return "Unicode"; | |
case 0xfeff: | |
return "UTF-16BE"; | |
default: | |
return "GBK"; | |
} | |
} | |
/** | |
* 获取文件行数 | |
* | |
* @param filePath 文件路径 | |
* @return 文件行数 | |
*/ | |
public static int getFileLines(StringfilePath) { | |
return getFileLines(getFileByPath(filePath)); | |
} | |
/** | |
* 获取文件行数 | |
* | |
* @param file 文件 | |
* @return 文件行数 | |
*/ | |
public static int getFileLines(File file) { | |
int count = 1; | |
InputStream is = null; | |
try { | |
is = new BufferedInputStream(newFileInputStream(file)); | |
byte[] buffer = new byte[1024]; | |
int readChars; | |
while ((readChars = is.read(buffer, 0, 1024)) != -1) { | |
for (int i= 0; i < readChars; ++i) { | |
if (buffer[i] == '\n')++count; | |
} | |
} | |
} catch (IOException e) { | |
e.printStackTrace(); | |
} finally { | |
CloseUtils.closeIO(is); | |
} | |
return count; | |
} | |
/** | |
* 获取目录大小 | |
* | |
* @param dirPath 目录路径 | |
* @return 文件大小 | |
*/ | |
public static String getDirSize(String dirPath) { | |
return getDirSize(getFileByPath(dirPath)); | |
} | |
/** | |
* 获取目录大小 | |
* | |
* @param dir 目录 | |
* @return 文件大小 | |
*/ | |
public static String getDirSize(File dir) { | |
long len = getDirLength(dir); | |
return len == -1? "": byte2FitMemorySize(len); | |
} | |
/** | |
* 获取文件大小 | |
* | |
* @param filePath 文件路径 | |
* @return 文件大小 | |
*/ | |
public static String getFileSize(StringfilePath) { | |
return getFileSize(getFileByPath(filePath)); | |
} | |
/** | |
* 获取文件大小 | |
* | |
* @param file 文件 | |
* @return 文件大小 | |
*/ | |
public static String getFileSize(File file) { | |
long len = getFileLength(file); | |
return len == -1? "": byte2FitMemorySize(len); | |
} | |
/** | |
* 获取目录长度 | |
* | |
* @param dirPath 目录路径 | |
* @return 文件大小 | |
*/ | |
public static long getDirLength(StringdirPath) { | |
return getDirLength(getFileByPath(dirPath)); | |
} | |
/** | |
* 获取目录长度 | |
* | |
* @param dir 目录 | |
* @return 文件大小 | |
*/ | |
public static long getDirLength(File dir) { | |
if (!isDir(dir))return -1; | |
long len = 0; | |
File[] files = dir.listFiles(); | |
if (files != null && files.length != 0) { | |
for (File file: files) { | |
if (file.isDirectory()) { | |
len += getDirLength(file); | |
} else { | |
len += file.length(); | |
} | |
} | |
} | |
return len; | |
} | |
/** | |
* 获取文件长度 | |
* | |
* @param filePath 文件路径 | |
* @return 文件大小 | |
*/ | |
public static long getFileLength(StringfilePath) { | |
return getFileLength(getFileByPath(filePath)); | |
} | |
/** | |
* 获取文件长度 | |
* | |
* @param file 文件 | |
* @return 文件大小 | |
*/ | |
public static long getFileLength(Filefile) { | |
if (!isFile(file))return -1; | |
return file.length(); | |
} | |
/** | |
* 获取文件的MD5校验码 | |
* | |
* @param filePath 文件路径 | |
* @return 文件的MD5校验码 | |
*/ | |
public static String getFileMD5ToString(StringfilePath) { | |
File file = isSpace(filePath) ?null : new File(filePath); | |
return getFileMD5ToString(file); | |
} | |
/** | |
* 获取文件的MD5校验码 | |
* | |
* @param filePath 文件路径 | |
* @return 文件的MD5校验码 | |
*/ | |
public static byte[] getFileMD5(String filePath) { | |
File file = isSpace(filePath) ?null : new File(filePath); | |
return getFileMD5(file); | |
} | |
/** | |
* 获取文件的MD5校验码 | |
* | |
* @param file 文件 | |
* @return 文件的MD5校验码 | |
*/ | |
public static String getFileMD5ToString(Filefile) { | |
return bytes2HexString(getFileMD5(file)); | |
} | |
/** | |
* 获取文件的MD5校验码 | |
* | |
* @param file 文件 | |
* @return 文件的MD5校验码 | |
*/ | |
public static byte[] getFileMD5(File file) { | |
if (file == null) return null; | |
DigestInputStream dis = null; | |
try { | |
FileInputStream fis = new FileInputStream(file); | |
MessageDigest md = MessageDigest.getInstance("MD5"); | |
dis = new DigestInputStream(fis, md); | |
byte[] buffer = new byte[1024 * 256]; | |
while (dis.read(buffer)> 0) ; | |
md = dis.getMessageDigest(); | |
return md.digest(); | |
} catch (NoSuchAlgorithmException| IOException e) { | |
e.printStackTrace(); | |
} finally { | |
CloseUtils.closeIO(dis); | |
} | |
return null; | |
} | |
/** | |
* 获取全路径中的最长目录 | |
* | |
* @param file 文件 | |
* @return filePath最长目录 | |
*/ | |
public static String getDirName(File file) { | |
if (file == null) return null; | |
return getDirName(file.getPath()); | |
} | |
/** | |
* 获取全路径中的最长目录 | |
* | |
* @param filePath 文件路径 | |
* @return filePath最长目录 | |
*/ | |
public static String getDirName(String filePath) { | |
if (isSpace(filePath)) return filePath; | |
int lastSep = filePath.lastIndexOf(File.separator); | |
return lastSep == -1? "": filePath.substring(0, lastSep+ 1); | |
} | |
/** | |
* 获取全路径中的文件名 | |
* | |
* @param file 文件 | |
* @return 文件名 | |
*/ | |
public static String getFileName(File file) { | |
if (file == null) return null; | |
return getFileName(file.getPath()); | |
} | |
/** | |
* 获取全路径中的文件名 | |
* | |
* @param filePath 文件路径 | |
* @return 文件名 | |
*/ | |
public static String getFileName(StringfilePath) { | |
if (isSpace(filePath)) return filePath; | |
int lastSep = filePath.lastIndexOf(File.separator); | |
return lastSep == -1? filePath : filePath.substring(lastSep+ 1); | |
} | |
/** | |
* 获取全路径中的不带拓展名的文件名 | |
* | |
* @param file 文件 | |
* @return 不带拓展名的文件名 | |
*/ | |
public static String getFileNameNoExtension(Filefile) { | |
if (file == null) return null; | |
return getFileNameNoExtension(file.getPath()); | |
} | |
/** | |
* 获取全路径中的不带拓展名的文件名 | |
* | |
* @param filePath 文件路径 | |
* @return 不带拓展名的文件名 | |
*/ | |
public static String getFileNameNoExtension(StringfilePath) { | |
if (isSpace(filePath)) return filePath; | |
int lastPoi = filePath.lastIndexOf('.'); | |
int lastSep = filePath.lastIndexOf(File.separator); | |
if (lastSep == -1) { | |
return (lastPoi == -1? filePath : filePath.substring(0, lastPoi)); | |
} | |
if (lastPoi == -1|| lastSep > lastPoi) { | |
return filePath.substring(lastSep+ 1); | |
} | |
return filePath.substring(lastSep+ 1, lastPoi); | |
} | |
/** | |
* 获取全路径中的文件拓展名 | |
* | |
* @param file 文件 | |
* @return 文件拓展名 | |
*/ | |
public static String getFileExtension(Filefile) { | |
if (file == null) return null; | |
return getFileExtension(file.getPath()); | |
} | |
/** | |
* 获取全路径中的文件拓展名 | |
* | |
* @param filePath 文件路径 | |
* @return 文件拓展名 | |
*/ | |
public static String getFileExtension(StringfilePath) { | |
if (isSpace(filePath)) return filePath; | |
int lastPoi = filePath.lastIndexOf('.'); | |
int lastSep = filePath.lastIndexOf(File.separator); | |
if (lastPoi == -1|| lastSep >= lastPoi) return ""; | |
return filePath.substring(lastPoi+ 1); | |
} | |
/** copy from ConvertUtils **/ | |
/** | |
* inputStream转byteArr | |
* | |
* @param is 输入流 | |
* @return 字节数组 | |
*/ | |
private static byte[] inputStream2Bytes(InputStreamis) { | |
if (is == null) return null; | |
return input2OutputStream(is).toByteArray(); | |
} | |
/** | |
* inputStream转outputStream | |
* | |
* @param is 输入流 | |
* @return outputStream子类 | |
*/ | |
private static ByteArrayOutputStreaminput2OutputStream(InputStreamis) { | |
if (is == null) return null; | |
try { | |
ByteArrayOutputStream os = new ByteArrayOutputStream(); | |
byte[] b = new byte[MemoryConstants.KB]; | |
int len; | |
while ((len = is.read(b, 0, MemoryConstants.KB))!= -1) { | |
os.write(b, 0, len); | |
} | |
return os; | |
} catch (IOException e) { | |
e.printStackTrace(); | |
return null; | |
} finally { | |
CloseUtils.closeIO(is); | |
} | |
} | |
private static final char hexDigits[] = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'}; | |
/** | |
* byteArr转hexString | |
* <p>例如:</p> | |
* bytes2HexString(new byte[] { 0, (byte) 0xa8 }) returns 00A8 | |
* | |
* @param bytes 字节数组 | |
* @return 16进制大写字符串 | |
*/ | |
private static String bytes2HexString(byte[]bytes) { | |
if (bytes == null) return null; | |
int len = bytes.length; | |
if (len <= 0) return null; | |
char[] ret = new char[len << 1]; | |
for (int i= 0, j = 0; i < len; i++) { | |
ret[j++] = hexDigits[bytes[i] >>>4 & 0x0f]; | |
ret[j++] = hexDigits[bytes[i] & 0x0f]; | |
} | |
return new String(ret); | |
} | |
/** | |
* 字节数转合适内存大小 | |
* <p>保留3位小数</p> | |
* | |
* @param byteNum 字节数 | |
* @return 合适内存大小 | |
*/ | |
@SuppressLint("DefaultLocale") | |
private static String byte2FitMemorySize(longbyteNum) { | |
if (byteNum < 0) { | |
return "shouldn't be less than zero!"; | |
} else if (byteNum < MemoryConstants.KB) { | |
return String.format("%.3fB", (double) byteNum + 0.0005); | |
} else if (byteNum < MemoryConstants.MB) { | |
return String.format("%.3fKB", (double) byteNum / MemoryConstants.KB+ 0.0005); | |
} else if (byteNum < MemoryConstants.GB) { | |
return String.format("%.3fMB", (double) byteNum / MemoryConstants.MB+ 0.0005); | |
} else { | |
return String.format("%.3fGB", (double) byteNum / MemoryConstants.GB+ 0.0005); | |
} | |
} | |
private static boolean isSpace(String s) { | |
if (s == null) return true; | |
for (int i= 0, len = s.length(); i< len; ++i) { | |
if (!Character.isWhitespace(s.charAt(i))) { | |
return false; | |
} | |
} | |
return true; | |
} | |
} |
文件相关→FileUtils
最新推荐文章于 2023-10-07 16:20:45 发布