package org.springside.modules.utils.io; 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.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.Iterator; import java.util.List; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.Validate; import org.springside.modules.utils.base.Platforms; import org.springside.modules.utils.base.annotation.NotNull; import org.springside.modules.utils.base.annotation.Nullable; import org.springside.modules.utils.text.Charsets; import com.google.common.io.Files; /** * 关于文件的工具集 * * 代码基本从调用Guava Files, 固定encoding为UTF8. * * 1.文件读写 * * 2.文件及目录操作 * * @author calvin */ public class FileUtil { //////// 文件读写////// /** * 读取文件到byte[]. */ public static byte[] toByteArray(final File file) throws IOException { return Files.toByteArray(file); } /** * 读取文件到String. */ public static String toString(final File file) throws IOException { return Files.toString(file, Charsets.UTF_8); } /** * 读取文件的每行内容到List<String> */ public static List<String> toLines(final File file) throws IOException { return Files.readLines(file, Charsets.UTF_8); } /** * 简单写入String到File. */ public static void write(final CharSequence data, final File file) throws IOException { Files.write(data, file, Charsets.UTF_8); } /** * 追加String到File. */ public static void append(final CharSequence from, final File to) throws IOException { Files.append(from, to, Charsets.UTF_8); } /** * 打开文件为InputStream */ public static InputStream asInputStream(String fileName) throws IOException { return new FileInputStream(getFileByPath(fileName)); } /** * 打开文件为InputStream */ public static InputStream asInputStream(File file) throws IOException { return new FileInputStream(file); } /** * 打开文件为OutputStream */ public static OutputStream asOututStream(String fileName) throws IOException { return new FileOutputStream(getFileByPath(fileName)); } /** * 打开文件为OutputStream */ public static OutputStream asOututStream(File file) throws IOException { return new FileOutputStream(file); } /** * 获取File的BufferedReader */ public static BufferedReader asBufferedReader(String fileName) throws FileNotFoundException { return Files.newReader(getFileByPath(fileName), Charsets.UTF_8); } /** * 获取File的BufferedWriter */ public static BufferedWriter asBufferedWriter(String fileName) throws FileNotFoundException { return Files.newWriter(getFileByPath(fileName), Charsets.UTF_8); } ///// 文件操作 ///// /** * 复制文件或目录 * * @param from 如果为null,或者是不存在的文件或目录,抛出异常. * @param to 如果为null,或者from是目录而to是已存在文件,或相反 */ public static void copy(@NotNull File from, @NotNull File to) throws IOException { Validate.notNull(from); Validate.notNull(to); if (from.isDirectory()) { copyDir(from, to); } else { copyFile(from, to); } } /** * 文件复制. * * @param from 如果为nll,或文件不存在或者是目录,,抛出异常 * @param to 如果to为null,或文件存在但是一个目录,抛出异常 */ public static void copyFile(@NotNull File from, @NotNull File to) throws IOException { Validate.isTrue(isFileExists(from), from + " is not exist or not a file"); Validate.notNull(to); Validate.isTrue(!FileUtil.isDirExists(to), to + " is exist but it is a dir"); Files.copy(from, to); } /** * 复制目录 */ public static void copyDir(@NotNull File from, @NotNull File to) throws IOException { Validate.isTrue(isDirExists(from), from + " is not exist or not a dir"); Validate.notNull(to); if (to.exists()) { Validate.isTrue(!to.isFile(), to + " is exist but it is a file"); } else { to.mkdirs(); } File[] files = from.listFiles(); if (files != null) { for (int i = 0; i < files.length; i++) { String name = files[i].getName(); if (".".equals(name) || "..".equals(name)) { continue; } copy(files[i], new File(to, name)); } } } /** * 文件移动/重命名. */ public static void moveFile(@NotNull File from, @NotNull File to) throws IOException { Validate.isTrue(isFileExists(from), from + " is not exist or not a file"); Validate.notNull(to); Validate.isTrue(!isDirExists(to), to + " is exist but it is a dir"); Files.move(from, to); } /** * 目录移动/重命名 */ public static void moveDir(@NotNull File from, @NotNull File to) throws IOException { Validate.isTrue(isDirExists(from), from + " is not exist or not a dir"); Validate.notNull(to); Validate.isTrue(!isFileExists(to), to + " is exist but it is a file"); final boolean rename = from.renameTo(to); if (!rename) { if (to.getCanonicalPath().startsWith(from.getCanonicalPath() + File.separator)) { throw new IOException("Cannot move directory: " + from + " to a subdirectory of itself: " + to); } copyDir(from, to); deleteDir(from); if (from.exists()) { throw new IOException("Failed to delete original directory '" + from + "' after copy to '" + to + '\''); } } } /** * 创建文件或更新时间戳. */ public static void touch(String filePath) throws IOException { Files.touch(getFileByPath(filePath)); } /** * 创建文件或更新时间戳. */ public static void touch(File file) throws IOException { Files.touch(file); } /** * 删除文件. * * 如果文件不存在或者是目录,则不做修改 */ public static void deleteFile(@Nullable File file) throws IOException { Validate.isTrue(isFileExists(file), file + " is not exist or not a file"); file.delete(); } /** * 删除目录及所有子目录/文件 */ public static void deleteDir(File dir) { Validate.isTrue(isDirExists(dir), dir + " is not exist or not a dir"); // 后序遍历,先删掉子目录中的文件/目录 Iterator<File> iterator = Files.fileTreeTraverser().postOrderTraversal(dir).iterator(); while (iterator.hasNext()) { iterator.next().delete(); } } /** * 判断目录是否存在, from Jodd */ public static boolean isDirExists(String dirPath) { return isDirExists(getFileByPath(dirPath)); } /** * 判断目录是否存在, from Jodd */ public static boolean isDirExists(File dir) { if (dir == null) { return false; } return dir.exists() && dir.isDirectory(); } /** * 确保目录存在, 如不存在则创建 */ public static void makesureDirExists(String dirPath) throws IOException { makesureDirExists(getFileByPath(dirPath)); } /** * 确保目录存在, 如不存在则创建 */ public static void makesureDirExists(File file) throws IOException { Validate.notNull(file); if (file.exists()) { if (!file.isDirectory()) { throw new IOException("There is a file exists " + file); } } else { file.mkdirs(); } } /** * 确保父目录及其父目录直到根目录都已经创建. * * @see Files#createParentDirs(File) */ public static void makesureParentDirExists(File file) throws IOException { Files.createParentDirs(file); } /** * 判断文件是否存在, from Jodd */ public static boolean isFileExists(String fileName) { return isFileExists(getFileByPath(fileName)); } /** * 判断文件是否存在, from Jodd */ public static boolean isFileExists(File file) { if (file == null) { return false; } return file.exists() && file.isFile(); } /** * 在临时目录创建临时目录,命名为${毫秒级时间戳}-${同一毫秒内的计数器}, from guava * * @see Files#createTempDir() */ public static File createTempDir() { return Files.createTempDir(); } /** * 在临时目录创建临时文件,命名为tmp-${random.nextLong()}.tmp */ public static File createTempFile() throws IOException { return File.createTempFile("tmp-", ".tmp"); } /** * 在临时目录创建临时文件,命名为${prefix}${random.nextLong()}${suffix} */ public static File createTempFile(String prefix, String suffix) throws IOException { return File.createTempFile(prefix, suffix); } private static File getFileByPath(String filePath) { return StringUtils.isBlank(filePath) ? null : new File(filePath); } /** * 获取文件名(不包含路径) */ public static String getFileName(@NotNull String fullName) { Validate.notEmpty(fullName); int last = fullName.lastIndexOf(Platforms.FILE_PATH_SEPARATOR_CHAR); return fullName.substring(last + 1); } /** * 获取文件名的扩展名部分(不包含.) */ public static String getFileExtension(File file) { return Files.getFileExtension(file.getName()); } /** * 获取文件名的扩展名部分(不包含.) */ public static String getFileExtension(String fullName) { return Files.getFileExtension(fullName); } }