xiejun
2024-11-01 80b6cbfc9c861469146318d0b3dd5f8b8b525b8a
Source/BladeX-Tool/blade-core-tool/src/main/java/org/springblade/core/tool/utils/FileUtil.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,383 @@
/*
 *      Copyright (c) 2018-2028, DreamLu All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions are met:
 *
 *  Redistributions of source code must retain the above copyright notice,
 *  this list of conditions and the following disclaimer.
 *  Redistributions in binary form must reproduce the above copyright
 *  notice, this list of conditions and the following disclaimer in the
 *  documentation and/or other materials provided with the distribution.
 *  Neither the name of the dreamlu.net developer nor the names of its
 *  contributors may be used to endorse or promote products derived from
 *  this software without specific prior written permission.
 *  Author: DreamLu å¢æ˜¥æ¢¦ (596392912@qq.com)
 */
package org.springblade.core.tool.utils;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.FileSystemUtils;
import org.springframework.util.PatternMatchUtils;
import org.springframework.web.multipart.MultipartFile;
import java.io.*;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.util.ArrayList;
import java.util.List;
/**
 * æ–‡ä»¶å·¥å…·ç±»
 *
 * @author L.cm
 */
public class FileUtil extends org.springframework.util.FileCopyUtils {
   /**
    * é»˜è®¤ä¸ºtrue
    *
    * @author L.cm
    */
   public static class TrueFilter implements FileFilter, Serializable {
      private static final long serialVersionUID = -6420452043795072619L;
      public final static TrueFilter TRUE = new TrueFilter();
      @Override
      public boolean accept(File pathname) {
         return true;
      }
   }
   /**
    * æ‰«æç›®å½•下的文件
    *
    * @param path è·¯å¾„
    * @return æ–‡ä»¶é›†åˆ
    */
   public static List<File> list(String path) {
      File file = new File(path);
      return list(file, TrueFilter.TRUE);
   }
   /**
    * æ‰«æç›®å½•下的文件
    *
    * @param path   è·¯å¾„
    * @param fileNamePattern æ–‡ä»¶å * å·
    * @return æ–‡ä»¶é›†åˆ
    */
   public static List<File> list(String path, final String fileNamePattern) {
      File file = new File(path);
      return list(file, pathname -> {
         String fileName = pathname.getName();
         return PatternMatchUtils.simpleMatch(fileNamePattern, fileName);
      });
   }
   /**
    * æ‰«æç›®å½•下的文件
    *
    * @param path   è·¯å¾„
    * @param filter æ–‡ä»¶è¿‡æ»¤
    * @return æ–‡ä»¶é›†åˆ
    */
   public static List<File> list(String path, FileFilter filter) {
      File file = new File(path);
      return list(file, filter);
   }
   /**
    * æ‰«æç›®å½•下的文件
    *
    * @param file æ–‡ä»¶
    * @return æ–‡ä»¶é›†åˆ
    */
   public static List<File> list(File file) {
      List<File> fileList = new ArrayList<>();
      return list(file, fileList, TrueFilter.TRUE);
   }
   /**
    * æ‰«æç›®å½•下的文件
    *
    * @param file   æ–‡ä»¶
    * @param fileNamePattern Spring AntPathMatcher è§„则
    * @return æ–‡ä»¶é›†åˆ
    */
   public static List<File> list(File file, final String fileNamePattern) {
      List<File> fileList = new ArrayList<>();
      return list(file, fileList, pathname -> {
         String fileName = pathname.getName();
         return PatternMatchUtils.simpleMatch(fileNamePattern, fileName);
      });
   }
   /**
    * æ‰«æç›®å½•下的文件
    *
    * @param file   æ–‡ä»¶
    * @param filter æ–‡ä»¶è¿‡æ»¤
    * @return æ–‡ä»¶é›†åˆ
    */
   public static List<File> list(File file, FileFilter filter) {
      List<File> fileList = new ArrayList<>();
      return list(file, fileList, filter);
   }
   /**
    * æ‰«æç›®å½•下的文件
    *
    * @param file   æ–‡ä»¶
    * @param filter æ–‡ä»¶è¿‡æ»¤
    * @return æ–‡ä»¶é›†åˆ
    */
   private static List<File> list(File file, List<File> fileList, FileFilter filter) {
      if (file.isDirectory()) {
         File[] files = file.listFiles();
         if (files != null) {
            for (File f : files) {
               list(f, fileList, filter);
            }
         }
      } else {
         // è¿‡æ»¤æ–‡ä»¶
         boolean accept = filter.accept(file);
         if (file.exists() && accept) {
            fileList.add(file);
         }
      }
      return fileList;
   }
   /**
    * èŽ·å–æ–‡ä»¶åŽç¼€å
    * @param fullName æ–‡ä»¶å…¨å
    * @return {String}
    */
   public static String getFileExtension(String fullName) {
      if (StringUtil.isBlank(fullName)) return StringPool.EMPTY;
      String fileName = new File(fullName).getName();
      int dotIndex = fileName.lastIndexOf(CharPool.DOT);
      return (dotIndex == -1) ? "" : fileName.substring(dotIndex + 1);
   }
   /**
    * èŽ·å–æ–‡ä»¶åï¼ŒåŽ»é™¤åŽç¼€å
    * @param fullName æ–‡ä»¶å…¨å
    * @return {String}
    */
   public static String getNameWithoutExtension(String fullName) {
      if (StringUtil.isBlank(fullName)) return StringPool.EMPTY;
      String fileName = new File(fullName).getName();
      int dotIndex = fileName.lastIndexOf(CharPool.DOT);
      return (dotIndex == -1) ? fileName : fileName.substring(0, dotIndex);
   }
   /**
    * Returns the path to the system temporary directory.
    *
    * @return the path to the system temporary directory.
    */
   public static String getTempDirPath() {
      return System.getProperty("java.io.tmpdir");
   }
   /**
    * Returns a {@link File} representing the system temporary directory.
    *
    * @return the system temporary directory.
    */
   public static File getTempDir() {
      return new File(getTempDirPath());
   }
   /**
    * Reads the contents of a file into a String.
    * The file is always closed.
    *
    * @param file the file to read, must not be {@code null}
    * @return the file contents, never {@code null}
    */
   public static String readToString(final File file) {
      return readToString(file, Charsets.UTF_8);
   }
   /**
    * Reads the contents of a file into a String.
    * The file is always closed.
    *
    * @param file     the file to read, must not be {@code null}
    * @param encoding the encoding to use, {@code null} means platform default
    * @return the file contents, never {@code null}
    */
   public static String readToString(final File file, final Charset encoding) {
      try (InputStream in = Files.newInputStream(file.toPath())) {
         return IoUtil.readToString(in, encoding);
      } catch (IOException e) {
         throw Exceptions.unchecked(e);
      }
   }
   /**
    * Reads the contents of a file into a String.
    * The file is always closed.
    *
    * @param file     the file to read, must not be {@code null}
    * @return the file contents, never {@code null}
    */
   public static byte[] readToByteArray(final File file) {
      try (InputStream in = Files.newInputStream(file.toPath())) {
         return IoUtil.readToByteArray(in);
      } catch (IOException e) {
         throw Exceptions.unchecked(e);
      }
   }
   /**
    * Writes a String to a file creating the file if it does not exist.
    *
    * @param file the file to write
    * @param data the content to write to the file
    */
   public static void writeToFile(final File file, final String data) {
      writeToFile(file, data, Charsets.UTF_8, false);
   }
   /**
    * Writes a String to a file creating the file if it does not exist.
    *
    * @param file   the file to write
    * @param data   the content to write to the file
    * @param append if {@code true}, then the String will be added to the
    *               end of the file rather than overwriting
    */
   public static void writeToFile(final File file, final String data, final boolean append){
      writeToFile(file, data, Charsets.UTF_8, append);
   }
   /**
    * Writes a String to a file creating the file if it does not exist.
    *
    * @param file     the file to write
    * @param data     the content to write to the file
    * @param encoding the encoding to use, {@code null} means platform default
    */
   public static void writeToFile(final File file, final String data, final Charset encoding) {
      writeToFile(file, data, encoding, false);
   }
   /**
    * Writes a String to a file creating the file if it does not exist.
    *
    * @param file     the file to write
    * @param data     the content to write to the file
    * @param encoding the encoding to use, {@code null} means platform default
    * @param append   if {@code true}, then the String will be added to the
    *                 end of the file rather than overwriting
    */
   public static void writeToFile(final File file, final String data, final Charset encoding, final boolean append) {
      try (OutputStream out = new FileOutputStream(file, append)) {
         IoUtil.write(data, out, encoding);
      } catch (IOException e) {
         throw Exceptions.unchecked(e);
      }
   }
   /**
    * è½¬æˆfile
    * @param multipartFile MultipartFile
    * @param file File
    */
   public static void toFile(MultipartFile multipartFile, final File file) {
      try {
         FileUtil.toFile(multipartFile.getInputStream(), file);
      } catch (IOException e) {
         throw Exceptions.unchecked(e);
      }
   }
   /**
    * è½¬æˆfile
    * @param in InputStream
    * @param file File
    */
   public static void toFile(InputStream in, final File file) {
      try (OutputStream out = new FileOutputStream(file)) {
         FileUtil.copy(in, out);
      } catch (IOException e) {
         throw Exceptions.unchecked(e);
      }
   }
   /**
    * Moves a file.
    * <p>
    * When the destination file is on another file system, do a "copy and delete".
    *
    * @param srcFile  the file to be moved
    * @param destFile the destination file
    * @throws NullPointerException if source or destination is {@code null}
    * @throws IOException          if source or destination is invalid
    * @throws IOException          if an IO error occurs moving the file
    */
   public static void moveFile(final File srcFile, final File destFile) throws IOException {
      Assert.notNull(srcFile, "Source must not be null");
      Assert.notNull(destFile, "Destination must not be null");
      if (!srcFile.exists()) {
         throw new FileNotFoundException("Source '" + srcFile + "' does not exist");
      }
      if (srcFile.isDirectory()) {
         throw new IOException("Source '" + srcFile + "' is a directory");
      }
      if (destFile.exists()) {
         throw new IOException("Destination '" + destFile + "' already exists");
      }
      if (destFile.isDirectory()) {
         throw new IOException("Destination '" + destFile + "' is a directory");
      }
      final boolean rename = srcFile.renameTo(destFile);
      if (!rename) {
         FileUtil.copy(srcFile, destFile);
         if (!srcFile.delete()) {
            FileUtil.deleteQuietly(destFile);
            throw new IOException("Failed to delete original file '" + srcFile + "' after copy to '" + destFile + "'");
         }
      }
   }
   /**
    * Deletes a file, never throwing an exception. If file is a directory, delete it and all sub-directories.
    * <p>
    * The difference between File.delete() and this method are:
    * <ul>
    * <li>A directory to be deleted does not have to be empty.</li>
    * <li>No exceptions are thrown when a file or directory cannot be deleted.</li>
    * </ul>
    *
    * @param file file or directory to delete, can be {@code null}
    * @return {@code true} if the file or directory was deleted, otherwise
    * {@code false}
    */
   public static boolean deleteQuietly(@Nullable final File file) {
      if (file == null) {
         return false;
      }
      try {
         if (file.isDirectory()) {
            FileSystemUtils.deleteRecursively(file);
         }
      } catch (final Exception ignored) {
      }
      try {
         return file.delete();
      } catch (final Exception ignored) {
         return false;
      }
   }
}