Skip to content

Commit

Permalink
springside#525 1.增加通配符匹配,对字符串可用通配符匹配,2.文件搜索可用AntPath,通配符,正则表达式匹配 3.Fi…
Browse files Browse the repository at this point in the history
…lePathUtils增加在windows下,将路径转为windows路径
  • Loading branch information
calvin1978 committed Jan 23, 2017
1 parent 1196602 commit 3222805
Show file tree
Hide file tree
Showing 13 changed files with 691 additions and 123 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ public abstract class Platforms {
// 文件路径分隔符
public static final String FILE_PATH_SEPARATOR = File.separator;
public static final char FILE_PATH_SEPARATOR_CHAR = File.separatorChar;
public static final char WINDOWS_FILE_PATH_SEPARATOR_CHAR='\\';
public static final char LINUX_FILE_PATH_SEPARATOR_CHAR='/';

// ClassPath分隔符
public static final String CLASS_PATH_SEPARATOR = File.pathSeparator;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,8 @@ public static boolean isNotEmpty(final Map<?, ?> map) {
*
* @see org.apache.commons.lang3.concurrent.ConcurrentUtils#putIfAbsent(ConcurrentMap, Object, Object)
*/
public static <K, V> V putIfAbsentWithFinalValue(final ConcurrentMap<K, V> map, final K key, final V value) {
public static <K, V> V putIfAbsentWithFinalValue(@NotNull final ConcurrentMap<K, V> map, final K key,
final V value) {
final V result = map.putIfAbsent(key, value);
return result != null ? result : value;
}
Expand All @@ -84,12 +85,8 @@ public static <K, V> V putIfAbsentWithFinalValue(final ConcurrentMap<K, V> map,
* @see org.apache.commons.lang3.concurrent.ConcurrentUtils#createIfAbsent(ConcurrentMap, Object,
* org.apache.commons.lang3.concurrent.ConcurrentInitializer)
*/
public static <K, V> V createIfAbsent(final ConcurrentMap<K, V> map, final K key,
final ValueCreator<? extends V> creator) {
if (map == null || creator == null) {
return null;
}

public static <K, V> V createIfAbsent(@NotNull final ConcurrentMap<K, V> map, final K key,
@NotNull final ValueCreator<? extends V> creator) {
final V value = map.get(key);
if (value == null) {
return putIfAbsentWithFinalValue(map, key, creator.get());
Expand All @@ -100,8 +97,6 @@ public static <K, V> V createIfAbsent(final ConcurrentMap<K, V> map, final K key
/**
* 创建Value值的回调函数
*
* from Common Lang
*
* @see MapUtil#createIfAbsent(ConcurrentMap, Object, ValueCreator)
*/
public interface ValueCreator<T> {
Expand Down Expand Up @@ -212,7 +207,7 @@ public static <C, K extends C, V> TreeMap<K, V> newSortedMap(@Nullable Comparato
/**
* 相比HashMap,当key是枚举类时, 性能与空间占用俱佳.
*/
public static <K extends Enum<K>, V> EnumMap<K, V> newEnumMap(Class<K> type) {
public static <K extends Enum<K>, V> EnumMap<K, V> newEnumMap(@NotNull Class<K> type) {
return new EnumMap<K, V>(Preconditions.checkNotNull(type));
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,49 +1,36 @@
package org.springside.modules.utils.io;

import java.io.File;

import org.apache.commons.lang3.Validate;
import org.apache.commons.lang3.StringUtils;
import org.springside.modules.utils.base.Platforms;
import org.springside.modules.utils.base.annotation.NotNull;
import org.springside.modules.utils.text.MoreStringUtil;

import com.google.common.io.Files;

/**
* 关于文件名,文件路径的工具集
* 关于文件路径的工具集
*
* @author calvin
*/
public abstract class FilePathUtil {

/**
* 获取文件名(不包含路径)
*/
public static String getFileName(@NotNull String fullName) {
Validate.notEmpty(fullName);
int last = fullName.lastIndexOf(Platforms.FILE_PATH_SEPARATOR_CHAR);
return fullName.substring(last + 1);
}

/**
* 获取文件名的扩展名部分(不包含.)
* 在Windows环境里,兼容Windows上的路径分割符,将 '/' 转回 '\'
*/
public static String getFileExtension(File file) {
return Files.getFileExtension(file.getName());
}
public static String normalizePath(String path) {
if (Platforms.FILE_PATH_SEPARATOR_CHAR == Platforms.WINDOWS_FILE_PATH_SEPARATOR_CHAR
&& StringUtils.indexOf(path, Platforms.LINUX_FILE_PATH_SEPARATOR_CHAR) != -1) {
return StringUtils.replaceChars(path, Platforms.LINUX_FILE_PATH_SEPARATOR_CHAR,
Platforms.WINDOWS_FILE_PATH_SEPARATOR_CHAR);
}
return path;

/**
* 获取文件名的扩展名部分(不包含.)
*/
public static String getFileExtension(String fullName) {
return Files.getFileExtension(fullName);
}

/**
* 将路径整理,如 "a/../b",整理成 "b"
*/
public static String simplifyPath(String pathName) {
return Files.simplifyPath(pathName);
public static String simplifyPath(String path) {
return Files.simplifyPath(path);
}

/**
Expand Down Expand Up @@ -76,4 +63,5 @@ public static String contact(String baseName, String... appendName) {
public static String getJarPath(Class<?> clazz) {
return clazz.getProtectionDomain().getCodeSource().getLocation().getFile();
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
package org.springside.modules.utils.io;

import java.io.File;
import java.util.List;
import java.util.regex.Pattern;

import org.springside.modules.utils.text.WildcardMatcher;

import com.google.common.base.Predicate;
import com.google.common.collect.TreeTraverser;
import com.google.common.io.Files;

public class FileTreeWalker {

/**
* 前序递归列出所有文件, 包含文件与目录,及根目录本身.
*
* 前序即先列出父目录,在列出子目录. 如要后序遍历, 直接使用Files.fileTreeTraverser()
*/
public static List<File> listAll(File rootDir) {
return Files.fileTreeTraverser().preOrderTraversal(rootDir).toList();
}

/**
* 前序递归列出所有文件, 只包含文件.
*/
public static List<File> listFile(File rootDir) {
return Files.fileTreeTraverser().preOrderTraversal(rootDir).filter(Files.isFile()).toList();
}

/**
* 前序递归列出所有文件, 列出后缀名匹配的文件. (后缀名不包含.)
*/
public static List<File> listFileWithExtension(final File rootDir, final String extension) {
return Files.fileTreeTraverser().preOrderTraversal(rootDir).filter(new FileExtensionFilter(extension)).toList();
}

/**
* 前序递归列出所有文件, 列出文件名匹配通配符的文件
*
* 如 ("/a/b/hello.txt", "he*") 将被返回
*/
public static List<File> listFileWithWildcardFileName(final File rootDir, final String fileNamePattern) {
return Files.fileTreeTraverser().preOrderTraversal(rootDir).filter(new WildcardFileNameFilter(fileNamePattern))
.toList();
}

/**
* 前序递归列出所有文件, 列出文件名匹配正则表达式的文件
*
* 如 ("/a/b/hello.txt", "he.*\.text") 将被返回
*/
public static List<File> listFileWithRegexFileName(final File rootDir, final String regexFileNamePattern) {
return Files.fileTreeTraverser().preOrderTraversal(rootDir)
.filter(new RegexFileNameFilter(regexFileNamePattern)).toList();
}

/**
* 前序递归列出所有文件, 列出符合ant path风格表达式的文件
*
* 如 ("/a/b/hello.txt", "he.*\.text") 将被返回
*/
public static List<File> listFileWithAntPath(final File rootDir, final String antPathPattern) {
return Files.fileTreeTraverser().preOrderTraversal(rootDir).filter(new AntPathFilter(antPathPattern)).toList();
}

/**
* 直接使用Guava的TreeTraverser,获得更大的灵活度, 比如加入各类filter,前序/后序的选择,一边遍历一边操作
*
* <pre>
* FileUtil.fileTreeTraverser().preOrderTraversal(root).iterator();
* </pre>
*/
public static TreeTraverser<File> fileTreeTraverser() {
return Files.fileTreeTraverser();
}

/**
* 以文件名正则表达式为filter,配合fileTreeTraverser使用
*/
public static final class RegexFileNameFilter implements Predicate<File> {
private final Pattern pattern;

private RegexFileNameFilter(String pattern) {
this.pattern = Pattern.compile(pattern);
}

@Override
public boolean apply(File input) {
return input.isFile() && pattern.matcher(input.getName()).matches();
}
}

/**
* 以文件名通配符为filter,配合fileTreeTraverser使用.
*
* @param pattern 支持*与?的通配符,如hello*.txt 匹配 helloworld.txt
*/
public static final class WildcardFileNameFilter implements Predicate<File> {
private final String pattern;

private WildcardFileNameFilter(String pattern) {
this.pattern = pattern;
}

@Override
public boolean apply(File input) {
return input.isFile() && WildcardMatcher.match(input.getName(), pattern);
}
}

/**
* 以文件名后缀做filter,配合fileTreeTraverser使用
*/
public static final class FileExtensionFilter implements Predicate<File> {
private final String extension;

private FileExtensionFilter(String extension) {
this.extension = extension;
}

@Override
public boolean apply(File input) {
return input.isFile() && extension.equals(FileUtil.getFileExtension(input));
}
}

/**
* 以ant风格的path为filter,配合fileTreeTraverser使用.
*
* @param pattern 支持ant风格的通配符,如/var/?/a?.txt 匹配 /var/b/ab.txt, 其他通配符包括**,*
*/
public static final class AntPathFilter implements Predicate<File> {
private final String pattern;

private AntPathFilter(String pattern) {
this.pattern = pattern;
}

@Override
public boolean apply(File input) {
return input.isFile() && WildcardMatcher.matchPath(input.getName(), pattern);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,11 @@

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.base.Predicate;
import com.google.common.collect.TreeTraverser;
import com.google.common.io.Files;

/**
Expand Down Expand Up @@ -223,40 +222,6 @@ public static void deleteDir(File dir) {
}
}

/**
* 前序递归列出所有文件, 包含文件与目录,及根目录本身.
*
* 前序即先列出父目录,在列出子目录. 如要后序遍历, 直接使用Files.fileTreeTraverser()
*/
public static List<File> listAll(File rootDir) {
return Files.fileTreeTraverser().preOrderTraversal(rootDir).toList();
}

/**
* 前序递归列出所有文件, 只包含文件.
*/
public static List<File> listFile(File rootDir) {
return Files.fileTreeTraverser().preOrderTraversal(rootDir).filter(Files.isFile()).toList();
}

/**
* 前序递归列出所有文件, 只包含后缀名匹配的文件. (后缀名不包含.)
*/
public static List<File> listFileWithExtension(final File rootDir, final String extension) {
return Files.fileTreeTraverser().preOrderTraversal(rootDir).filter(new FileExtensionFilter(extension)).toList();
}

/**
* 直接使用Guava的TreeTraverser,获得更大的灵活度, 比如加入各类filter,前序/后序的选择,一边遍历一边操作
*
* <pre>
* FileUtil.fileTreeTraverser().preOrderTraversal(root).iterator();
* </pre>
*/
public static TreeTraverser<File> fileTreeTraverser() {
return Files.fileTreeTraverser();
}

/**
* 判断目录是否存在, from Jodd
*/
Expand Down Expand Up @@ -349,18 +314,26 @@ private static File getFileByPath(String filePath) {
}

/**
* 以文件名后缀做filter,配合fileTreeTraverser使用
* 获取文件名(不包含路径)
*/
public static final class FileExtensionFilter implements Predicate<File> {
private final String extension;
public static String getFileName(@NotNull String fullName) {
Validate.notEmpty(fullName);
int last = fullName.lastIndexOf(Platforms.FILE_PATH_SEPARATOR_CHAR);
return fullName.substring(last + 1);
}

private FileExtensionFilter(String extension) {
this.extension = extension;
}
/**
* 获取文件名的扩展名部分(不包含.)
*/
public static String getFileExtension(File file) {
return Files.getFileExtension(file.getName());
}

@Override
public boolean apply(File input) {
return input.isFile() && extension.equals(FilePathUtil.getFileExtension(input));
}
/**
* 获取文件名的扩展名部分(不包含.)
*/
public static String getFileExtension(String fullName) {
return Files.getFileExtension(fullName);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,10 @@
*
* 所以resourceName无需以"/"打头即表示jar file中的根目录,带了"/" 反而导致JarFile.getEntry(resouceName)时没有返回.
*
* 指定contextClass时,class.getResource()会先对name进行处理再交给classLoader,打头的"/"的会被去除,不以"/"打头则表示与该contextClass package的相对路径, 会先转为绝对路径.
* 指定contextClass时,class.getResource()会先对name进行处理再交给classLoader,打头的"/"的会被去除,不以"/"打头则表示与该contextClass package的相对路径,
* 会先转为绝对路径.
*
* 3.同名资源
* 3.同名资源
*
* 如果有多个同名资源,除非调用getResources()获取全部资源,否则在URLClassLoader中按ClassPath顺序打开第一个命中的Jar文件.
*/
Expand Down
Loading

0 comments on commit 3222805

Please sign in to comment.