檔案操作工具類: 檔案/目錄的建立、刪除、移動、複製、zip壓縮與解壓.
阿新 • • 發佈:2019-01-04
package com.xnl.utils; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.File; import java.io.FileFilter; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.FilenameFilter; import java.io.InputStream; import java.io.OutputStream; import java.util.Arrays; import org.apache.commons.io.FileUtils; import org.apache.tools.ant.Project; import org.apache.tools.ant.taskdefs.Expand; import org.apache.tools.zip.ZipEntry; import org.apache.tools.zip.ZipOutputStream; /** * 檔案操作工具類: * 檔案/目錄的建立、刪除、移動、複製、zip壓縮與解壓 * 檔案操作過程中要注意是否有操作許可權的問題,以免報錯。 * commons-io-2.5.jar * ant-1.6.5.jar * @date 2017年3月1日 * @author xnl */ public class FileOperations { /*使用GBK編碼避免壓縮中文檔名亂碼*/ private static final String CHINESE_CHARSET = "GBK"; /*檔案讀取緩衝區大小*/ private static final int CACHE_SIZE = 1024 * 50; /** * 壓縮檔案或資料夾為zip格式檔案 * @param sourceFile 檔案或資料夾 * @param zipFilePath 壓縮檔案輸出路徑(以.zip結尾) * @throws Exception */ public static void zip(String sourceFile, String zipFilePath) throws Exception { File sourcefile = new File(sourceFile); if (!sourcefile.exists()) { throw new Exception("指定的檔案不存在!"); } File zipFile = new File(zipFilePath); if (!zipFile.getParentFile().exists()) { // 如果目標檔案的父目錄不存在,則建立父目錄 new File(zipFile.getParentFile().getPath()).mkdirs(); } OutputStream out = new FileOutputStream(zipFilePath); BufferedOutputStream bos = new BufferedOutputStream(out); ZipOutputStream zos = new ZipOutputStream(bos); zos.setEncoding(CHINESE_CHARSET);// 解決中文檔名亂碼問題 String basePath = null; if (sourcefile.isDirectory()) { basePath = sourcefile.getPath(); } else { basePath = sourcefile.getParent(); } zipFile(sourcefile, basePath, zos); zos.closeEntry(); zos.close(); bos.close(); out.close(); } /** * 遞迴壓縮檔案 * @param parentFile * @param basePath * @param zos * @throws Exception */ private static void zipFile(File parentFile, String basePath, ZipOutputStream zos) throws Exception { File[] files = new File[0]; if (parentFile.isDirectory()) { files = parentFile.listFiles(); } else { files = new File[1]; files[0] = parentFile; } String pathName; InputStream is; BufferedInputStream bis; byte[] cache = new byte[CACHE_SIZE]; for (File file : files) { // TODO 判斷檔案是否正在讀寫中,如果是,則不壓縮該檔案。 if (!file.renameTo(file)) { continue; } if (file.isDirectory()) { pathName = file.getPath().substring(basePath.length() + 1) + File.separator; zos.putNextEntry(new ZipEntry(pathName)); zipFile(file, basePath, zos); } else { pathName = file.getPath().substring(basePath.length() + 1); is = new FileInputStream(file); bis = new BufferedInputStream(is); zos.putNextEntry(new ZipEntry(pathName)); int nRead = 0; while ((nRead = bis.read(cache, 0, CACHE_SIZE)) != -1) { zos.write(cache, 0, nRead); } bis.close(); is.close(); } } } /** * 功能:壓縮多個檔案成一個zip檔案 * @param sourceFile:原始檔列表 * @param targetZipFile:壓縮後的檔案 * @throws Exception */ public static void zipFiles(File[] sourceFiles, File targetZipFile) throws Exception { byte[] buf = new byte[CACHE_SIZE]; ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(targetZipFile)); zos.setEncoding(CHINESE_CHARSET);// 解決中文檔名亂碼問題 FileInputStream fis = null; for (int i = 0; i < sourceFiles.length; i++) { fis = new FileInputStream(sourceFiles[i]); zos.putNextEntry(new ZipEntry(sourceFiles[i].getName())); int len; while ((len = fis.read(buf)) > 0) { zos.write(buf, 0, len); } if (zos != null) { zos.closeEntry(); } if (fis != null) { fis.close(); } } if (zos != null) { zos.close(); } } /** * 解壓指定的zip壓縮包到目標目錄 * 對應的是ant-1.6.5.jar * @param sourceFile 指定的zip壓縮包檔案 * @param destDir 目標目錄 * @throws Exception */ public static void unzip(String sourceFile, String destDir) throws Exception { Project p = new Project(); Expand expand = new Expand(); expand.setProject(p); expand.setSrc(new File(sourceFile)); expand.setOverwrite(false); expand.setDest(new File(destDir)); expand.setEncoding(CHINESE_CHARSET); expand.execute(); } /** * copy普通檔案到目標資料夾下 * @param sourceFile 原始檔路徑 * @param targetDir 目標資料夾路徑 * @throws Exception */ public static void copyFileToDir(String sourceFile, String targetDir) throws Exception { File source = new File(sourceFile); File target = new File(targetDir); FileUtils.copyFileToDirectory(source, target); } /** * copy普通檔案到目標檔案,可實現檔案同目錄改名 * @param sourceFile 普通檔案 * @param targetFile 目標檔案 * @throws Exception */ public static void copyFileToFile(String sourceFile, String targetFile) throws Exception { File source = new File(sourceFile); File target = new File(targetFile); FileUtils.copyFile(source, target); } /** * copy指定資料夾到目標資料夾 * @param sourceDir 指定原資料夾 * @param targetDir 目標資料夾 * @throws Exception */ public static void copyDirToDir(String sourceDir, String targetDir) throws Exception { File source = new File(sourceDir); File target = new File(targetDir); FileUtils.copyDirectoryToDirectory(source, target); } /** * 刪除指定的資料夾(遞迴刪除多級目錄) * 注意:不論資料夾是否為空都可以刪除 * @param sourceDir 指定的資料夾路徑 * @throws Exception */ public static void deleteDir(String sourceDir) throws Exception { File directory = new File(sourceDir); FileUtils.deleteDirectory(directory); } /** * 刪除檔案或資料夾, * 注意:不論資料夾是否為空都可以刪除,請慎用 * @param sourceFilePath 指定的檔案\資料夾路徑 */ public static void deleteFile(String sourceFilePath) { File source = new File(sourceFilePath); FileUtils.deleteQuietly(source); } /** * 指定檔案移動到目標檔案,可以實現指定檔案的同目錄下改名,同時會刪除原檔案 * @param sourceFile 指定檔案路徑 * @param targetFile 目標檔案路徑 * @throws Exception */ public static void moveFileToFile(String sourceFile, String targetFile) throws Exception { File source = new File(sourceFile); File target = new File(targetFile); FileUtils.moveFile(source, target); } /** * 指定檔案移動到目標目錄下,同時會刪除原檔案 * @param sourceFile 指定檔案 * @param targetDir 目標目錄 * @throws Exception */ public static void moveFileToDir(String sourceFile, String targetDir) throws Exception { File source = new File(sourceFile); File target = new File(targetDir); FileUtils.moveToDirectory(source, target, true); } /** * 指定目錄移動到目標目錄,同時會刪除原目錄 * @param sourceDir 指定源目錄 * @param targetDir 目標目錄 * @throws Exception */ public static void moveDirToDir(String sourceDir, String targetDir) throws Exception { File source = new File(sourceDir); File target = new File(targetDir); FileUtils.moveDirectoryToDirectory(source, target, true); } /** * 建立單個普通檔案(不能是目錄) * @param descFileName 檔名,包含路徑 * @return 如果檔案建立成功,則返回true,否則返回false * @throws Exception */ public static boolean createFile(String descFileName) throws Exception { File file = new File(descFileName); if (file.exists()) { // 如果檔案已經存在,則建立失敗 return false; } if (descFileName.endsWith(File.separator)) { // 如果檔案路徑以'/'結尾,則是目錄,不能建立目錄 return false; } if (!file.getParentFile().exists()) { // 如果檔案的父目錄不存在,則需要建立 // 如果檔案所在的目錄不存在,則建立目錄 if (!file.getParentFile().mkdirs()) { // 如果父目錄建立失敗,則檔案建立也失敗 return false; } } if (file.createNewFile()) { // 檔案建立成功 return true; } else { // 檔案建立失敗 return false; } } /** * 建立目錄 * @param descDirName 目錄名,包含路徑 * @return 如果目錄建立成功,則返回true,否則返回false */ public static boolean createDirectory(String descDirName) { String descDirNames = descDirName; if (!descDirNames.endsWith(File.separator)) { descDirNames = descDirNames + File.separator; } File descDir = new File(descDirNames); if (descDir.exists()) { // 目錄已經存在,則建立失敗 return false; } if (descDir.mkdirs()) { // 建立成功 return true; } else { // 建立失敗 return false; } } /** * 壓縮指定資料夾下符合匹配規則的檔案到目標目錄下 * @param regex 匹配規則 * @param sourceDir 原始檔夾 * @param targetZipFile 目標zip檔案的路徑及名稱 * @param isEnd 是否以regex匹配規則結尾,為true則表示按照副檔名過濾,false則表示按照檔名(除副檔名外)過濾 * @throws Exception */ public static void zip(String regex, String sourceDir, String targetZipFile, boolean isEnd) throws Exception { File sourceDirFile = new File(sourceDir); File targetZip = new File(targetZipFile); if (!targetZip.getParentFile().exists()) { new File(targetZip.getParent()).mkdirs(); } File[] files = null; if (!isEmpty(regex) && isEnd) { // 原始檔夾下符合過濾條件的檔案,不包含子資料夾中的檔案在內 files = sourceDirFile.listFiles(new ExtensionFilter(regex)); } else if (!isEmpty(regex) && !isEnd) { // 原始檔夾符合過濾條件的所有檔案及資料夾的路徑及名稱,不包含子資料夾中的檔案或資料夾在內 files = sourceDirFile.listFiles(new NameFilter(regex)); } else { // 原始檔夾下的所有的檔案/資料夾的路徑及名稱,不包含子資料夾內的檔案/資料夾 files = sourceDirFile.listFiles(); } System.out.println(Arrays.toString(files)); if (files != null && files.length > 0) { zipFiles(files, targetZip); } else { throw new Exception("不存在符合匹配規則的檔案!"); } } private static boolean isEmpty(String str) { if (str == null || "".equals(str)) { return true; } return false; } } /**檔名過濾器,只匹配符合規則的檔案,不包括資料夾*/ class NameFilter implements FilenameFilter { /*匹配規則*/ private String regex; public NameFilter(String regex) { this.regex = regex; } @Override public boolean accept(File dir, String name) { File f = new File(dir.getPath() + File.separator + name); if (f.isDirectory()) { return false; } if (name.contains(".")) { name = name.substring(0, name.lastIndexOf(".")); // 將檔名的副檔名去掉 } if (name.indexOf(regex) > -1) { return true; } return false; } } /**副檔名過濾器,只匹配符合規則的檔案,不包括資料夾*/ class ExtensionFilter implements FileFilter { /*匹配規則*/ private String regex; public ExtensionFilter(String regex) { this.regex = regex; } @Override public boolean accept(File pathname) { if (pathname.isDirectory()) { return false; } String filename = pathname.getName(); boolean isMatched = filename.endsWith(regex); if (pathname.isFile() && isMatched) { return true; } return false; } }