package org.quickbundle.tools.helper.io; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.Closeable; import java.io.File; import java.io.FileFilter; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; import java.io.OutputStreamWriter; import java.io.PrintWriter; import java.io.RandomAccessFile; import java.io.StringReader; import java.nio.channels.FileChannel; import java.util.ArrayList; import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; import org.quickbundle.config.RmBaseConfig; import org.quickbundle.tools.helper.RmDateHelper; import org.quickbundle.util.RmString; public class RmFileHelper { /** * @param fileList * @return */ public static List<String> getFiles(String fileList) { List<String> result = new ArrayList<String>(); String[] files = fileList.split(","); for(String f : files) { f = f.trim(); if(f.length() == 0) { continue; } if(f.indexOf("*") > -1) { f = formatToFile(f).replaceAll("[/\\\\]+", "/"); String beforeAndStar = f.substring(0, f.indexOf("*")+1); String afterStar = f.substring(f.indexOf("*")+1); Pattern pParent = Pattern.compile("^(.*[/])([^/]+?)$"); Matcher mt = pParent.matcher(beforeAndStar); if(mt.find()) { String parent = mt.group(1); String abstractFile = mt.group(2) + afterStar; String newFilePattern = abstractFile.replaceAll("([.-])", "\\\\$1"); newFilePattern = newFilePattern.replaceAll("\\*", ".*"); final String fNewFilePattern = newFilePattern; final File fParent = new File(parent); if(!fParent.exists()) { continue; } final String formatFParent = fParent.getAbsolutePath().replaceAll("[/\\\\]+", "/"); List<File> fFinals = recursiveGetFile(fParent, new FileFilter() { public boolean accept(File pathname) { String formatF = pathname.getAbsolutePath().replaceAll("[/\\\\]+", "/"); String tail = formatF.substring(formatFParent.length()); return Pattern.matches(fNewFilePattern, tail); } }); for(File fFinal : fFinals) { if(!result.contains(fFinal.getAbsolutePath())) { result.add(fFinal.getAbsolutePath()); } } } } else { if(!result.contains(f)) { result.add(f); } } } return result; } /** * 递归获得文件 * * @param f * @param ff * @return */ static List<File> recursiveGetFile(File f, FileFilter ff) { List<File> lf = new ArrayList<File>(); if (f.isFile()) { if (ff.accept(f)) { lf.add(f); } } else { File[] fs = f.listFiles(); for (File tempF : fs) { lf.addAll(recursiveGetFile(tempF, ff)); } } return lf; } /** * 功能: 将路径格式化为url --> file:///c:/rmdemo.log * * @param filePath * @return */ public static String formatToUrl(String filePath) { if(filePath == null) { return null; } filePath = filePath.replaceFirst("file:[/\\\\]*", ""); filePath = filePath.replaceAll("[/\\\\]+", "/"); if (filePath.startsWith("/")) { filePath = "file://" + filePath; } else { filePath = "file:///" + filePath; } return filePath; } /** * 功能: 将路径格式化为url --> c:/rmdemo.log * * @param filePath * @return */ public static String formatToUrlNoPrefix(String filePath) { if(filePath == null) { return null; } filePath = formatToUrl(filePath); if(File.separator.endsWith("/")) { filePath = filePath.substring("file://".length()); } else { filePath = filePath.substring("file:///".length()); } return filePath; } /** * 功能: 将路径格式化为File形式 --> c:\rmdemo.log * * @param filePath * @param osSeparatorStr 指定当前操作系统分隔符 * @return */ public static String formatToFile(String filePath, String osSeparatorStr) { if(filePath == null) { return null; } String osSeparatorRegex = ("\\".equals(osSeparatorStr)) ? "\\\\" : osSeparatorStr; filePath = filePath.replaceFirst("file:[/\\\\]*", ""); filePath = filePath.replaceAll("[/\\\\]+", osSeparatorRegex); //自动补齐Linux下的/ if("/".equals(osSeparatorStr) && !filePath.startsWith("/")) { filePath = "/" + filePath; } return filePath; } /** * 功能: 将路径格式化为File形式 --> c:\rmdemo.log * * @param filePString * @return */ public static String formatToFile(String filePString) { return formatToFile(filePString, File.separator); } /** * 显示数据前过滤掉null * * @param myString * @return */ public static String prt(String myString) { if (myString != null) return myString; else return ""; } /** * 功能: 拷贝文件 * * @param sourceFile * @param targetFile * @return * @throws Exception */ public static boolean copyFile_reader(File sourceFile, File targetFile) throws Exception { BufferedReader in1 = null; PrintWriter out1 = null; initParentDir(targetFile.getPath()); try { in1 = new BufferedReader(new FileReader(sourceFile)); out1 = new PrintWriter(new BufferedWriter(new FileWriter(targetFile))); String s = null; while ((s = in1.readLine()) != null) { out1.println(s); } return true; } catch (Exception e) { e.printStackTrace(); throw e; } finally { try { if (in1 != null) { out1.close(); } if (out1 != null) { out1.close(); } } catch (Exception e) { } } } /** * 功能: 拷贝文件 * * @param sourceFile * @param targetFile * @return * @throws Exception */ private static boolean copyFile_old(File sourceFile, File targetFile) throws Exception { FileInputStream input = null; BufferedInputStream inBuff = null; FileOutputStream output = null; BufferedOutputStream outBuff = null; try { // 新建文件输入流并对它进行缓冲 input = new FileInputStream(sourceFile); inBuff=new BufferedInputStream(input); // 新建文件输出流并对它进行缓冲 output = new FileOutputStream(targetFile); outBuff = new BufferedOutputStream(output); // 缓冲数组 byte[] b = new byte[1024 * 5]; int len; while ((len =inBuff.read(b)) != -1) { outBuff.write(b, 0, len); } // 刷新此缓冲的输出流 outBuff.flush(); //关闭流 inBuff.close(); outBuff.close(); output.close(); input.close(); return true; } catch (Exception e) { e.printStackTrace(); throw e; } finally { try { if (input != null) { input.close(); } if (inBuff != null) { inBuff.close(); } if (output != null) { output.close(); } if (outBuff != null) { outBuff.close(); } } catch (Exception e) { } } } /** * 功能: 保存String到targetFile中 * * @param context * @param targetFile * @return * @throws Exception */ public static boolean saveFile(String context, String targetFile) throws Exception { BufferedReader in1 = null; BufferedWriter out1 = null; initParentDir(targetFile); try { in1 = new BufferedReader(new StringReader(context)); out1 = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(targetFile), RmBaseConfig.getSingleton().getDefaultEncode())); String s = null; boolean isFirstLine = true; while ((s = in1.readLine()) != null) { if(!isFirstLine) { out1.write("\n"); } out1.write(s); isFirstLine = false; } return true; } catch (Exception e) { e.printStackTrace(); throw e; } finally { try { if (in1 != null) { out1.close(); } if (out1 != null) { out1.close(); } } catch (Exception e) { } } } /** * 功能: 为目标创建父目录 * * @param targetPath */ public static String initParentDir(String targetPath) { String formatPath = formatToFile(targetPath); File targetFile = new File(formatPath); if (!targetFile.getParentFile().exists()) { targetFile.getParentFile().mkdirs(); } return targetFile.getParent(); } /** * 功能: 为目标创建目录并返回 * * @param targetPath */ public static String initSelfDir(String targetPath) { String formatPath = formatToFile(targetPath); File targetFile = new File(formatPath); if (!targetFile.exists()) { targetFile.mkdirs(); } return targetFile.getAbsolutePath(); } /** * 复制整个文件夹内容 * * @param oldPath String 原文件路径 * @param newPath String 复制后路径 * @return boolean */ public static void copyFolder(String oldPath, String newPath) { oldPath = formatToFile(oldPath); newPath = formatToFile(newPath); FileInputStream input = null; FileOutputStream output = null; try { (new File(newPath)).mkdirs(); //如果文件夹不存在 则建立新文件夹 File a = new File(oldPath); String[] file = a.list(); File temp = null; for (int i = 0; i < file.length; i++) { if (oldPath.endsWith(File.separator)) { temp = new File(oldPath + file[i]); } else { temp = new File(oldPath + File.separator + file[i]); } if (temp.isFile()) { input = new FileInputStream(temp); output = new FileOutputStream(newPath + "/" + (temp.getName()).toString()); byte[] b = new byte[1024 * 5]; int len; while ((len = input.read(b)) != -1) { output.write(b, 0, len); } output.flush(); } if (temp.isDirectory()) {//如果是子文件夹 copyFolder(oldPath + "/" + file[i], newPath + "/" + file[i]); } } } catch (Exception e) { System.out.println("复制整个文件夹内容操作出错"); e.printStackTrace(); } finally { try { if (input != null) { input.close(); } if (output != null) { output.close(); } } catch (Exception e1) { e1.printStackTrace(); } } } /** * 功能: 随机访问文件tartetPath,把context插到afterKeyWord后边 * * @param targetPath * @param context * @param afterKeyWord */ public static void writeToRandomFile(String targetPath, String context, String afterKeyWord) { BufferedReader in = null; RandomAccessFile rf = null; targetPath = formatToFile(targetPath); try { if (new File(targetPath).exists()) { //检查是否已经存在相同代码 in = new BufferedReader(new FileReader(targetPath)); String s1 = null; StringBuilder tempStr = new StringBuilder(); boolean isFirstLine = true; while ((s1 = in.readLine()) != null) { if(!isFirstLine) { tempStr.append("\n"); } tempStr.append(s1); isFirstLine = false; } if (tempStr.indexOf(context) >= 0) { //已经存在 return; } } { String line = null; long position = 0; rf = new RandomAccessFile(targetPath, "rw"); while (true) { line = rf.readLine(); if (line != null) { if (line.trim().equals(afterKeyWord)) { position = rf.getFilePointer(); break; } } else { position = rf.getFilePointer(); break; } } StringBuilder originRemain = new StringBuilder(); boolean isFirstLine = true; while ((line = rf.readLine()) != null) { if(!isFirstLine) { originRemain.append("\n"); } originRemain.append(line); isFirstLine = false; } rf.seek(position); rf.write(context.getBytes(RmBaseConfig.getSingleton().getDefaultEncode())); rf.writeBytes(originRemain.toString()); } } catch (FileNotFoundException e) { throw new RuntimeException(e); } catch (IOException e) { throw new RuntimeException(e); } finally { try { if (rf != null) { rf.close(); } } catch (IOException e2) { e2.printStackTrace(); } } } /** * 递归删除目录 * * @param filepath * @throws IOException */ public static void delDir(String filepath) throws IOException { File f = new File(filepath);// 定义文件路径 if (f.exists() && f.isDirectory()) {// 判断是文件还是目录 if (f.listFiles().length == 0) {// 若目录下没有文件则直接删除 f.delete(); } else {// 若有则把文件放进数组,并判断是否有下级目录 File delFile[] = f.listFiles(); int i = f.listFiles().length; for (int j = 0; j < i; j++) { if (delFile[j].isDirectory()) { delDir(delFile[j].getAbsolutePath());// 递归调用del方法并取得子目录路径 } delFile[j].delete();// 删除文件 } f.delete(); } } } /** * 移动文件 * * @param source * @param target * @return * @throws IOException */ public static boolean renameTo(File source, File target) throws IOException { if (!source.renameTo(target)) { copyFile(source, target); return source.delete(); } return true; } /** * 执行逻辑删除文件,把文件移动到全局配置的回收站。否则直接删除文件 * 可以在rm.xml设置开关 * @param f 源文件 * @return 如果移动失败,不会删除源文件,返回false。 如果移动成功,删除源文件,返回true * @throws IOException */ public static boolean delete(File f) throws IOException { if(RmBaseConfig.getSingleton().isLogicDeleteFile()) { String recycle = RmBaseConfig.getSingleton().getRecycleBinFolder(); File fRecycle = new File(recycle); if(!fRecycle.exists()) { fRecycle.mkdirs(); } File fToDelete = new File(recycle + File.separator + System.nanoTime() + "$" + f.getName()); if (!f.renameTo(fToDelete)) { copyFile(f, fToDelete); f.delete(); } return true; } else { return f.delete(); } } /** * The number of bytes in a kilobyte. */ public static final long ONE_KB = 1024; /** * The number of bytes in a megabyte. */ public static final long ONE_MB = ONE_KB * ONE_KB; /** * The file copy buffer size (30 MB) */ private static final long FILE_COPY_BUFFER_SIZE = ONE_MB * 30; /** * Copies a file to a new location preserving the file date. * <p> * This method copies the contents of the specified source file to the * specified destination file. The directory holding the destination file is * created if it does not exist. If the destination file exists, then this * method will overwrite it. * <p> * <strong>Note:</strong> This method tries to preserve the file's last * modified date/times using {@link File#setLastModified(long)}, however * it is not guaranteed that the operation will succeed. * If the modification operation fails, no indication is provided. * * @param srcFile an existing file to copy, must not be <code>null</code> * @param destFile the new file, must not be <code>null</code> * * @throws NullPointerException if source or destination is <code>null</code> * @throws IOException if source or destination is invalid * @throws IOException if an IO error occurs during copying * @see #copyFileToDirectory(File, File) */ public static void copyFile(File srcFile, File destFile) throws IOException { copyFile(srcFile, destFile, true); } /** * Copies a file to a new location. * <p> * This method copies the contents of the specified source file * to the specified destination file. * The directory holding the destination file is created if it does not exist. * If the destination file exists, then this method will overwrite it. * <p> * <strong>Note:</strong> Setting <code>preserveFileDate</code> to * <code>true</code> tries to preserve the file's last modified * date/times using {@link File#setLastModified(long)}, however it is * not guaranteed that the operation will succeed. * If the modification operation fails, no indication is provided. * * @param srcFile an existing file to copy, must not be <code>null</code> * @param destFile the new file, must not be <code>null</code> * @param preserveFileDate true if the file date of the copy * should be the same as the original * * @throws NullPointerException if source or destination is <code>null</code> * @throws IOException if source or destination is invalid * @throws IOException if an IO error occurs during copying * @see #copyFileToDirectory(File, File, boolean) */ public static void copyFile(File srcFile, File destFile, boolean preserveFileDate) throws IOException { if (srcFile == null) { throw new NullPointerException("Source must not be null"); } if (destFile == null) { throw new NullPointerException("Destination must not be null"); } if (srcFile.exists() == false) { throw new FileNotFoundException("Source '" + srcFile + "' does not exist"); } if (srcFile.isDirectory()) { throw new IOException("Source '" + srcFile + "' exists but is a directory"); } if (srcFile.getCanonicalPath().equals(destFile.getCanonicalPath())) { throw new IOException("Source '" + srcFile + "' and destination '" + destFile + "' are the same"); } File parentFile = destFile.getParentFile(); if (parentFile != null) { if (!parentFile.mkdirs() && !parentFile.isDirectory()) { throw new IOException("Destination '" + parentFile + "' directory cannot be created"); } } if (destFile.exists() && destFile.canWrite() == false) { throw new IOException("Destination '" + destFile + "' exists but is read-only"); } doCopyFile(srcFile, destFile, preserveFileDate); } /** * Internal copy file method. * * @param srcFile the validated source file, must not be <code>null</code> * @param destFile the validated destination file, must not be <code>null</code> * @param preserveFileDate whether to preserve the file date * @throws IOException if an error occurs */ private static void doCopyFile(File srcFile, File destFile, boolean preserveFileDate) throws IOException { if (destFile.exists() && destFile.isDirectory()) { throw new IOException("Destination '" + destFile + "' exists but is a directory"); } FileInputStream fis = null; FileOutputStream fos = null; FileChannel input = null; FileChannel output = null; try { fis = new FileInputStream(srcFile); fos = new FileOutputStream(destFile); input = fis.getChannel(); output = fos.getChannel(); long size = input.size(); long pos = 0; long count = 0; while (pos < size) { count = size - pos > FILE_COPY_BUFFER_SIZE ? FILE_COPY_BUFFER_SIZE : size - pos; pos += output.transferFrom(input, pos, count); } } finally { closeQuietly(output); closeQuietly(fos); closeQuietly(input); closeQuietly(fis); } if (srcFile.length() != destFile.length()) { throw new IOException("Failed to copy full contents from '" + srcFile + "' to '" + destFile + "'"); } if (preserveFileDate) { destFile.setLastModified(srcFile.lastModified()); } } /** * Unconditionally close a <code>Closeable</code>. * <p> * Equivalent to {@link Closeable#close()}, except any exceptions will be ignored. * This is typically used in finally blocks. * <p> * Example code: * <pre> * Closeable closeable = null; * try { * closeable = new FileReader("foo.txt"); * // process closeable * closeable.close(); * } catch (Exception e) { * // error handling * } finally { * IOUtils.closeQuietly(closeable); * } * </pre> * * @param closeable the object to close, may be null or already closed * @since 2.0 */ public static void closeQuietly(Closeable closeable) { try { if (closeable != null) { closeable.close(); } } catch (IOException ioe) { // ignore } } public static String fileToString(File file) throws IOException { StringBuilder str = new StringBuilder(); long totalSize = 0; str.append("卷("); str.append(file.toString()); str.append(")的文件夹 PATH 列表\n"); str.append("卷信息\t"); str.append(" 存在:"); str.append(file.exists()); str.append(" 是文件夹:"); str.append(file.isDirectory()); str.append(" 能读:"); str.append(file.canRead()); str.append(" 能写:"); str.append(file.canWrite()); str.append(" 是否隐藏:"); str.append(file.isHidden()); str.append(" 最后修改时间:"); str.append(RmDateHelper.getFormatDateTimeDesc(file.lastModified())); str.append("\n"); str.append(file.getAbsoluteFile()); str.append("\n"); RmString rmstr = listFileRecursive(file, "│├─", totalSize); str.append(rmstr.toString()); str.append("\n总大小:"); str.append(((Long)rmstr.getAttribute("totalSize")).longValue() / 1024); str.append(" k, "); str.append(((Long)rmstr.getAttribute("totalSize")).longValue()); str.append("B."); return str.toString(); } private static RmString listFileRecursive(File file, String sign, long totalSize) throws IOException { RmString rmstr = new RmString(); if (rmstr.getAttribute("totalSize") == null) { rmstr.addAttribute("totalSize", new Long(0)); } StringBuilder str = new StringBuilder(); File[] fileChild = file.listFiles(); if (fileChild != null) { int fileSum = 0, folderSum = 0; { // 计算文件和文件夹个数 for (int i = 0; i < fileChild.length; i++) { if (fileChild[i].isFile()) { fileSum++; } else if (fileChild[i].isDirectory()) { folderSum++; } } } for (int i = 0; i < fileChild.length; i++) { if (fileChild[i].isFile()) { fileSum++; if (folderSum > 0) { str.append(sign.replaceAll("│├─", "│ ")); str.append(fileChild[i].getName()); str.append("\n"); } else { str.append(sign.replaceAll("│├─", " ")); str.append(fileChild[i].getName()); str.append("\n"); } { // 计算大小 long currentSize = ((Long)rmstr.getAttribute("totalSize")).longValue() + fileChild[i].length(); rmstr.addAttribute("totalSize", new Long(currentSize)); } } } if (fileSum > 0 && folderSum > 0) { str.append(sign.replaceAll("│├─", "│ ")); str.append("\n"); } int tempFolderIndex = 0; for (int i = 0; i < fileChild.length; i++) { if (fileChild[i].isDirectory()) { RmString tempRmstr = null; if (tempFolderIndex == folderSum - 1) { str.append(sign.replaceAll("│├─", "└──")); str.append(fileChild[i].getName()); str.append("\n"); tempRmstr = listFileRecursive(fileChild[i], (sign + " ").replaceAll("│├─ ", " │├─"), totalSize); } else { str.append(sign.replaceAll("│├─", "├──")); str.append(fileChild[i].getName()); str.append("\n"); tempRmstr = listFileRecursive(fileChild[i], (sign + " ").replaceAll("│├─ ", "│ │├─"), totalSize); } { long currentSize = ((Long)rmstr.getAttribute("totalSize")).longValue() + ((Long)tempRmstr.getAttribute("totalSize")).longValue(); rmstr.addAttribute("totalSize", new Long(currentSize)); str.append(tempRmstr); } tempFolderIndex++; } } } rmstr.setValue(str.toString()); return rmstr; } public static void main(String[] args) { List<String> lf = getFiles("E:/platform/myProject/qbrm/code/QbRmWebDemo/src/main/*/vo/Rm*java,E:/platform/myProject/qbrm/code/QbRmWebDemo/src/test/*/*java"); for(String s : lf) { System.out.println(s); } } }