一、前言
关于apache的commons-io包中org.apache.commons.io.FilenameUtils文件名工具类对文件名跨操作系统识别isSystemWindows或separatorsToUnix或separatorsToWindows、规范化处理doNormalize、获取文件全路径getFullPath、分隔text处理splitOnTokens等。
二、源码说明
package org.apache.commons.io;@b@@b@import java.io.File;@b@import java.util.ArrayList;@b@import java.util.Collection;@b@import java.util.Stack;@b@@b@public class FilenameUtils@b@{@b@ public static final char EXTENSION_SEPARATOR = 46;@b@ public static final String EXTENSION_SEPARATOR_STR = Character.toString('.');@b@ private static final char UNIX_SEPARATOR = 47;@b@ private static final char WINDOWS_SEPARATOR = 92;@b@ private static final char SYSTEM_SEPARATOR = File.separatorChar;@b@ private static final char OTHER_SEPARATOR;@b@@b@ static boolean isSystemWindows()@b@ {@b@ return (SYSTEM_SEPARATOR == '\\');@b@ }@b@@b@ private static boolean isSeparator(char ch)@b@ {@b@ return ((ch == '/') || (ch == '\\'));@b@ }@b@@b@ public static String normalize(String filename)@b@ {@b@ return doNormalize(filename, SYSTEM_SEPARATOR, true);@b@ }@b@@b@ public static String normalize(String filename, boolean unixSeparator)@b@ {@b@ char separator = (unixSeparator) ? '/' : '\\';@b@ return doNormalize(filename, separator, true);@b@ }@b@@b@ public static String normalizeNoEndSeparator(String filename)@b@ {@b@ return doNormalize(filename, SYSTEM_SEPARATOR, false);@b@ }@b@@b@ public static String normalizeNoEndSeparator(String filename, boolean unixSeparator)@b@ {@b@ char separator = (unixSeparator) ? '/' : '\\';@b@ return doNormalize(filename, separator, false);@b@ }@b@@b@ private static String doNormalize(String filename, char separator, boolean keepSeparator)@b@ {@b@ if (filename == null)@b@ return null;@b@@b@ int size = filename.length();@b@ if (size == 0)@b@ return filename;@b@@b@ int prefix = getPrefixLength(filename);@b@ if (prefix < 0) {@b@ return null;@b@ }@b@@b@ char[] array = new char[size + 2];@b@ filename.getChars(0, filename.length(), array, 0);@b@@b@ char otherSeparator = (separator == SYSTEM_SEPARATOR) ? OTHER_SEPARATOR : SYSTEM_SEPARATOR;@b@ for (int i = 0; i < array.length; ++i) {@b@ if (array[i] == otherSeparator) {@b@ array[i] = separator;@b@ }@b@@b@ }@b@@b@ boolean lastIsDirectory = true;@b@ if (array[(size - 1)] != separator) {@b@ array[(size++)] = separator;@b@ lastIsDirectory = false;@b@ }@b@@b@ for (int i = prefix + 1; i < size; ++i) {@b@ if ((array[i] == separator) && (array[(i - 1)] == separator)) {@b@ System.arraycopy(array, i, array, i - 1, size - i);@b@ --size;@b@ --i;@b@ }@b@@b@ }@b@@b@ for (i = prefix + 1; i < size; ++i) {@b@ if ((array[i] == separator) && (array[(i - 1)] == '.') && (((i == prefix + 1) || (array[(i - 2)] == separator))))@b@ {@b@ if (i == size - 1)@b@ lastIsDirectory = true;@b@@b@ System.arraycopy(array, i + 1, array, i - 1, size - i);@b@ size -= 2;@b@ --i;@b@ }@b@@b@ }@b@@b@ for (i = prefix + 2; i < size; ++i)@b@ if ((array[i] == separator) && (array[(i - 1)] == '.') && (array[(i - 2)] == '.') && (((i == prefix + 2) || (array[(i - 3)] == separator))))@b@ {@b@ if (i == prefix + 2)@b@ return null;@b@@b@ if (i == size - 1) {@b@ lastIsDirectory = true;@b@ }@b@@b@ for (int j = i - 4; j >= prefix; --j)@b@ if (array[j] == separator)@b@ {@b@ System.arraycopy(array, i + 1, array, j + 1, size - i);@b@ size -= i - j;@b@ i = j + 1;@b@ break label464:@b@ }@b@@b@@b@ System.arraycopy(array, i + 1, array, prefix, size - i);@b@ size -= i + 1 - prefix;@b@ i = prefix + 1;@b@ }@b@@b@@b@ if (size <= 0)@b@ label464: return "";@b@@b@ if (size <= prefix)@b@ return new String(array, 0, size);@b@@b@ if ((lastIsDirectory) && (keepSeparator))@b@ return new String(array, 0, size);@b@@b@ return new String(array, 0, size - 1);@b@ }@b@@b@ public static String concat(String basePath, String fullFilenameToAdd)@b@ {@b@ int prefix = getPrefixLength(fullFilenameToAdd);@b@ if (prefix < 0)@b@ return null;@b@@b@ if (prefix > 0)@b@ return normalize(fullFilenameToAdd);@b@@b@ if (basePath == null)@b@ return null;@b@@b@ int len = basePath.length();@b@ if (len == 0)@b@ return normalize(fullFilenameToAdd);@b@@b@ char ch = basePath.charAt(len - 1);@b@ if (isSeparator(ch))@b@ return normalize(basePath + fullFilenameToAdd);@b@@b@ return normalize(basePath + '/' + fullFilenameToAdd);@b@ }@b@@b@ public static String separatorsToUnix(String path)@b@ {@b@ if ((path == null) || (path.indexOf(92) == -1))@b@ return path;@b@@b@ return path.replace('\\', '/');@b@ }@b@@b@ public static String separatorsToWindows(String path)@b@ {@b@ if ((path == null) || (path.indexOf(47) == -1))@b@ return path;@b@@b@ return path.replace('/', '\\');@b@ }@b@@b@ public static String separatorsToSystem(String path)@b@ {@b@ if (path == null)@b@ return null;@b@@b@ if (isSystemWindows())@b@ return separatorsToWindows(path);@b@@b@ return separatorsToUnix(path);@b@ }@b@@b@ public static int getPrefixLength(String filename)@b@ {@b@ if (filename == null)@b@ return -1;@b@@b@ int len = filename.length();@b@ if (len == 0)@b@ return 0;@b@@b@ char ch0 = filename.charAt(0);@b@ if (ch0 == ':')@b@ return -1;@b@@b@ if (len == 1) {@b@ if (ch0 == '~')@b@ return 2;@b@@b@ return ((isSeparator(ch0)) ? 1 : 0);@b@ }@b@ if (ch0 == '~') {@b@ int posUnix = filename.indexOf(47, 1);@b@ int posWin = filename.indexOf(92, 1);@b@ if ((posUnix == -1) && (posWin == -1))@b@ return (len + 1);@b@@b@ posUnix = (posUnix == -1) ? posWin : posUnix;@b@ posWin = (posWin == -1) ? posUnix : posWin;@b@ return (Math.min(posUnix, posWin) + 1);@b@ }@b@ char ch1 = filename.charAt(1);@b@ if (ch1 == ':') {@b@ ch0 = Character.toUpperCase(ch0);@b@ if ((ch0 >= 'A') && (ch0 <= 'Z')) {@b@ if ((len == 2) || (!(isSeparator(filename.charAt(2)))))@b@ return 2;@b@@b@ return 3;@b@ }@b@ return -1;@b@ }@b@ if ((isSeparator(ch0)) && (isSeparator(ch1))) {@b@ int posUnix = filename.indexOf(47, 2);@b@ int posWin = filename.indexOf(92, 2);@b@ if (((posUnix == -1) && (posWin == -1)) || (posUnix == 2) || (posWin == 2))@b@ return -1;@b@@b@ posUnix = (posUnix == -1) ? posWin : posUnix;@b@ posWin = (posWin == -1) ? posUnix : posWin;@b@ return (Math.min(posUnix, posWin) + 1);@b@ }@b@ return ((isSeparator(ch0)) ? 1 : 0);@b@ }@b@@b@ public static int indexOfLastSeparator(String filename)@b@ {@b@ if (filename == null)@b@ return -1;@b@@b@ int lastUnixPos = filename.lastIndexOf(47);@b@ int lastWindowsPos = filename.lastIndexOf(92);@b@ return Math.max(lastUnixPos, lastWindowsPos);@b@ }@b@@b@ public static int indexOfExtension(String filename)@b@ {@b@ if (filename == null)@b@ return -1;@b@@b@ int extensionPos = filename.lastIndexOf(46);@b@ int lastSeparator = indexOfLastSeparator(filename);@b@ return ((lastSeparator > extensionPos) ? -1 : extensionPos);@b@ }@b@@b@ public static String getPrefix(String filename)@b@ {@b@ if (filename == null)@b@ return null;@b@@b@ int len = getPrefixLength(filename);@b@ if (len < 0)@b@ return null;@b@@b@ if (len > filename.length())@b@ return filename + '/';@b@@b@ return filename.substring(0, len);@b@ }@b@@b@ public static String getPath(String filename)@b@ {@b@ return doGetPath(filename, 1);@b@ }@b@@b@ public static String getPathNoEndSeparator(String filename)@b@ {@b@ return doGetPath(filename, 0);@b@ }@b@@b@ private static String doGetPath(String filename, int separatorAdd)@b@ {@b@ if (filename == null)@b@ return null;@b@@b@ int prefix = getPrefixLength(filename);@b@ if (prefix < 0)@b@ return null;@b@@b@ int index = indexOfLastSeparator(filename);@b@ int endIndex = index + separatorAdd;@b@ if ((prefix >= filename.length()) || (index < 0) || (prefix >= endIndex))@b@ return "";@b@@b@ return filename.substring(prefix, endIndex);@b@ }@b@@b@ public static String getFullPath(String filename)@b@ {@b@ return doGetFullPath(filename, true);@b@ }@b@@b@ public static String getFullPathNoEndSeparator(String filename)@b@ {@b@ return doGetFullPath(filename, false);@b@ }@b@@b@ private static String doGetFullPath(String filename, boolean includeSeparator)@b@ {@b@ if (filename == null)@b@ return null;@b@@b@ int prefix = getPrefixLength(filename);@b@ if (prefix < 0)@b@ return null;@b@@b@ if (prefix >= filename.length()) {@b@ if (includeSeparator)@b@ return getPrefix(filename);@b@@b@ return filename;@b@ }@b@@b@ int index = indexOfLastSeparator(filename);@b@ if (index < 0)@b@ return filename.substring(0, prefix);@b@@b@ int end = index + ((includeSeparator) ? 1 : 0);@b@ if (end == 0)@b@ ++end;@b@@b@ return filename.substring(0, end);@b@ }@b@@b@ public static String getName(String filename)@b@ {@b@ if (filename == null)@b@ return null;@b@@b@ int index = indexOfLastSeparator(filename);@b@ return filename.substring(index + 1);@b@ }@b@@b@ public static String getBaseName(String filename)@b@ {@b@ return removeExtension(getName(filename));@b@ }@b@@b@ public static String getExtension(String filename)@b@ {@b@ if (filename == null)@b@ return null;@b@@b@ int index = indexOfExtension(filename);@b@ if (index == -1)@b@ return "";@b@@b@ return filename.substring(index + 1);@b@ }@b@@b@ public static String removeExtension(String filename)@b@ {@b@ if (filename == null)@b@ return null;@b@@b@ int index = indexOfExtension(filename);@b@ if (index == -1)@b@ return filename;@b@@b@ return filename.substring(0, index);@b@ }@b@@b@ public static boolean equals(String filename1, String filename2)@b@ {@b@ return equals(filename1, filename2, false, IOCase.SENSITIVE);@b@ }@b@@b@ public static boolean equalsOnSystem(String filename1, String filename2)@b@ {@b@ return equals(filename1, filename2, false, IOCase.SYSTEM);@b@ }@b@@b@ public static boolean equalsNormalized(String filename1, String filename2)@b@ {@b@ return equals(filename1, filename2, true, IOCase.SENSITIVE);@b@ }@b@@b@ public static boolean equalsNormalizedOnSystem(String filename1, String filename2)@b@ {@b@ return equals(filename1, filename2, true, IOCase.SYSTEM);@b@ }@b@@b@ public static boolean equals(String filename1, String filename2, boolean normalized, IOCase caseSensitivity)@b@ {@b@ if ((filename1 == null) || (filename2 == null))@b@ return ((filename1 == null) && (filename2 == null));@b@@b@ if (normalized) {@b@ filename1 = normalize(filename1);@b@ filename2 = normalize(filename2);@b@ if ((filename1 == null) || (filename2 == null))@b@ throw new NullPointerException("Error normalizing one or both of the file names");@b@@b@ }@b@@b@ if (caseSensitivity == null)@b@ caseSensitivity = IOCase.SENSITIVE;@b@@b@ return caseSensitivity.checkEquals(filename1, filename2);@b@ }@b@@b@ public static boolean isExtension(String filename, String extension)@b@ {@b@ if (filename == null)@b@ return false;@b@@b@ if ((extension == null) || (extension.length() == 0))@b@ return (indexOfExtension(filename) == -1);@b@@b@ String fileExt = getExtension(filename);@b@ return fileExt.equals(extension);@b@ }@b@@b@ public static boolean isExtension(String filename, String[] extensions)@b@ {@b@ if (filename == null)@b@ return false;@b@@b@ if ((extensions == null) || (extensions.length == 0))@b@ return (indexOfExtension(filename) == -1);@b@@b@ String fileExt = getExtension(filename);@b@ String[] arr$ = extensions; int len$ = arr$.length; for (int i$ = 0; i$ < len$; ++i$) { String extension = arr$[i$];@b@ if (fileExt.equals(extension))@b@ return true;@b@ }@b@@b@ return false;@b@ }@b@@b@ public static boolean isExtension(String filename, Collection<String> extensions)@b@ {@b@ if (filename == null)@b@ return false;@b@@b@ if ((extensions == null) || (extensions.isEmpty()))@b@ return (indexOfExtension(filename) == -1);@b@@b@ String fileExt = getExtension(filename);@b@ for (String extension : extensions)@b@ if (fileExt.equals(extension))@b@ return true;@b@@b@@b@ return false;@b@ }@b@@b@ public static boolean wildcardMatch(String filename, String wildcardMatcher)@b@ {@b@ return wildcardMatch(filename, wildcardMatcher, IOCase.SENSITIVE);@b@ }@b@@b@ public static boolean wildcardMatchOnSystem(String filename, String wildcardMatcher)@b@ {@b@ return wildcardMatch(filename, wildcardMatcher, IOCase.SYSTEM);@b@ }@b@@b@ public static boolean wildcardMatch(String filename, String wildcardMatcher, IOCase caseSensitivity)@b@ {@b@ if ((filename == null) && (wildcardMatcher == null))@b@ return true;@b@@b@ if ((filename == null) || (wildcardMatcher == null))@b@ return false;@b@@b@ if (caseSensitivity == null)@b@ caseSensitivity = IOCase.SENSITIVE;@b@@b@ String[] wcs = splitOnTokens(wildcardMatcher);@b@ boolean anyChars = false;@b@ int textIdx = 0;@b@ int wcsIdx = 0;@b@ Stack backtrack = new Stack();@b@ do@b@ {@b@ if (backtrack.size() > 0) {@b@ int[] array = (int[])backtrack.pop();@b@ wcsIdx = array[0];@b@ textIdx = array[1];@b@ anyChars = true;@b@ }@b@@b@ while (wcsIdx < wcs.length)@b@ {@b@ if (wcs[wcsIdx].equals("?"))@b@ {@b@ ++textIdx;@b@ if (textIdx > filename.length())@b@ break;@b@@b@ anyChars = false;@b@ }@b@ else if (wcs[wcsIdx].equals("*"))@b@ {@b@ anyChars = true;@b@ if (wcsIdx == wcs.length - 1)@b@ textIdx = filename.length();@b@@b@ }@b@ else@b@ {@b@ if (anyChars)@b@ {@b@ textIdx = caseSensitivity.checkIndexOf(filename, textIdx, wcs[wcsIdx]);@b@ if (textIdx == -1)@b@ {@b@ break;@b@ }@b@ int repeat = caseSensitivity.checkIndexOf(filename, textIdx + 1, wcs[wcsIdx]);@b@ if (repeat >= 0) {@b@ backtrack.push(new int[] { wcsIdx, repeat });@b@ }@b@@b@ }@b@ else if (!(caseSensitivity.checkRegionMatches(filename, textIdx, wcs[wcsIdx])))@b@ {@b@ break;@b@ }@b@@b@ textIdx += wcs[wcsIdx].length();@b@ anyChars = false;@b@ }@b@@b@ ++wcsIdx;@b@ }@b@@b@ if ((wcsIdx == wcs.length) && (textIdx == filename.length()))@b@ return true;@b@ }@b@@b@ while (backtrack.size() > 0);@b@@b@ return false;@b@ }@b@@b@ static String[] splitOnTokens(String text)@b@ {@b@ if ((text.indexOf(63) == -1) && (text.indexOf(42) == -1)) {@b@ return new String[] { text };@b@ }@b@@b@ char[] array = text.toCharArray();@b@ ArrayList list = new ArrayList();@b@ StringBuilder buffer = new StringBuilder();@b@ for (int i = 0; i < array.length; ++i)@b@ if ((array[i] == '?') || (array[i] == '*')) {@b@ if (buffer.length() != 0) {@b@ list.add(buffer.toString());@b@ buffer.setLength(0);@b@ }@b@ if (array[i] == '?')@b@ list.add("?");@b@ else if ((list.size() == 0) || ((i > 0) && (!(((String)list.get(list.size() - 1)).equals("*")))))@b@ {@b@ list.add("*");@b@ }@b@ } else {@b@ buffer.append(array[i]);@b@ }@b@@b@ if (buffer.length() != 0) {@b@ list.add(buffer.toString());@b@ }@b@@b@ return ((String[])list.toArray(new String[list.size()]));@b@ }@b@@b@ static@b@ {@b@ if (isSystemWindows())@b@ OTHER_SEPARATOR = '/';@b@ else@b@ OTHER_SEPARATOR = '\\';@b@ }@b@}