?? filenameutils.java
字號:
size -= (i - j);
i = j + 1;
continue outer;
}
}
// remove a/../ from a/../c
System.arraycopy(array, i + 1, array, prefix, size - i);
size -= (i + 1 - prefix);
i = prefix + 1;
}
}
if (size <= 0) { // should never be less than 0
return "";
}
if (size <= prefix) { // should never be less than prefix
return new String(array, 0, size);
}
if (lastIsDirectory && keepSeparator) {
return new String(array, 0, size); // keep trailing separator
}
return new String(array, 0, size - 1); // lose trailing separator
}
//-----------------------------------------------------------------------
/**
* Concatenates a filename to a base path using normal command line style rules.
* <p>
* The effect is equivalent to resultant directory after changing
* directory to the first argument, followed by changing directory to
* the second argument.
* <p>
* The first argument is the base path, the second is the path to concatenate.
* The returned path is always normalized via {@link #normalize(String)},
* thus <code>..</code> is handled.
* <p>
* If <code>pathToAdd</code> is absolute (has an absolute prefix), then
* it will be normalized and returned.
* Otherwise, the paths will be joined, normalized and returned.
* <p>
* The output will be the same on both Unix and Windows except
* for the separator character.
* <pre>
* /foo/ + bar --> /foo/bar
* /foo + bar --> /foo/bar
* /foo + /bar --> /bar
* /foo + C:/bar --> C:/bar
* /foo + C:bar --> C:bar (*)
* /foo/a/ + ../bar --> foo/bar
* /foo/ + ../../bar --> null
* /foo/ + /bar --> /bar
* /foo/.. + /bar --> /bar
* /foo + bar/c.txt --> /foo/bar/c.txt
* /foo/c.txt + bar --> /foo/c.txt/bar (!)
* </pre>
* (*) Note that the Windows relative drive prefix is unreliable when
* used with this method.
* (!) Note that the first parameter must be a path. If it ends with a name, then
* the name will be built into the concatenated path. If this might be a problem,
* use {@link #getFullPath(String)} on the base path argument.
*
* @param basePath the base path to attach to, always treated as a path
* @param fullFilenameToAdd the filename (or path) to attach to the base
* @return the concatenated path, or null if invalid
*/
public static String concat(String basePath, String fullFilenameToAdd) {
int prefix = getPrefixLength(fullFilenameToAdd);
if (prefix < 0) {
return null;
}
if (prefix > 0) {
return normalize(fullFilenameToAdd);
}
if (basePath == null) {
return null;
}
int len = basePath.length();
if (len == 0) {
return normalize(fullFilenameToAdd);
}
char ch = basePath.charAt(len - 1);
if (isSeparator(ch)) {
return normalize(basePath + fullFilenameToAdd);
} else {
return normalize(basePath + '/' + fullFilenameToAdd);
}
}
//-----------------------------------------------------------------------
/**
* Converts all separators to the Unix separator of forward slash.
*
* @param path the path to be changed, null ignored
* @return the updated path
*/
public static String separatorsToUnix(String path) {
if (path == null || path.indexOf(WINDOWS_SEPARATOR) == -1) {
return path;
}
return path.replace(WINDOWS_SEPARATOR, UNIX_SEPARATOR);
}
/**
* Converts all separators to the Windows separator of backslash.
*
* @param path the path to be changed, null ignored
* @return the updated path
*/
public static String separatorsToWindows(String path) {
if (path == null || path.indexOf(UNIX_SEPARATOR) == -1) {
return path;
}
return path.replace(UNIX_SEPARATOR, WINDOWS_SEPARATOR);
}
/**
* Converts all separators to the system separator.
*
* @param path the path to be changed, null ignored
* @return the updated path
*/
public static String separatorsToSystem(String path) {
if (path == null) {
return null;
}
if (SYSTEM_SEPARATOR == WINDOWS_SEPARATOR) {
return separatorsToWindows(path);
} else {
return separatorsToUnix(path);
}
}
//-----------------------------------------------------------------------
/**
* Returns the length of the filename prefix, such as <code>C:/</code> or <code>~/</code>.
* <p>
* This method will handle a file in either Unix or Windows format.
* <p>
* The prefix length includes the first slash in the full filename
* if applicable. Thus, it is possible that the length returned is greater
* than the length of the input string.
* <pre>
* Windows:
* a\b\c.txt --> "" --> relative
* \a\b\c.txt --> "\" --> current drive absolute
* C:a\b\c.txt --> "C:" --> drive relative
* C:\a\b\c.txt --> "C:\" --> absolute
* \\server\a\b\c.txt --> "\\server\" --> UNC
*
* Unix:
* a/b/c.txt --> "" --> relative
* /a/b/c.txt --> "/" --> absolute
* ~/a/b/c.txt --> "~/" --> current user
* ~ --> "~/" --> current user (slash added)
* ~user/a/b/c.txt --> "~user/" --> named user
* ~user --> "~user/" --> named user (slash added)
* </pre>
* <p>
* The output will be the same irrespective of the machine that the code is running on.
* ie. both Unix and Windows prefixes are matched regardless.
*
* @param filename the filename to find the prefix in, null returns -1
* @return the length of the prefix, -1 if invalid or null
*/
public static int getPrefixLength(String filename) {
if (filename == null) {
return -1;
}
int len = filename.length();
if (len == 0) {
return 0;
}
char ch0 = filename.charAt(0);
if (ch0 == ':') {
return -1;
}
if (len == 1) {
if (ch0 == '~') {
return 2; // return a length greater than the input
}
return (isSeparator(ch0) ? 1 : 0);
} else {
if (ch0 == '~') {
int posUnix = filename.indexOf(UNIX_SEPARATOR, 1);
int posWin = filename.indexOf(WINDOWS_SEPARATOR, 1);
if (posUnix == -1 && posWin == -1) {
return len + 1; // return a length greater than the input
}
posUnix = (posUnix == -1 ? posWin : posUnix);
posWin = (posWin == -1 ? posUnix : posWin);
return Math.min(posUnix, posWin) + 1;
}
char ch1 = filename.charAt(1);
if (ch1 == ':') {
ch0 = Character.toUpperCase(ch0);
if (ch0 >= 'A' && ch0 <= 'Z') {
if (len == 2 || isSeparator(filename.charAt(2)) == false) {
return 2;
}
return 3;
}
return -1;
} else if (isSeparator(ch0) && isSeparator(ch1)) {
int posUnix = filename.indexOf(UNIX_SEPARATOR, 2);
int posWin = filename.indexOf(WINDOWS_SEPARATOR, 2);
if ((posUnix == -1 && posWin == -1) || posUnix == 2 || posWin == 2) {
return -1;
}
posUnix = (posUnix == -1 ? posWin : posUnix);
posWin = (posWin == -1 ? posUnix : posWin);
return Math.min(posUnix, posWin) + 1;
} else {
return (isSeparator(ch0) ? 1 : 0);
}
}
}
/**
* Returns the index of the last directory separator character.
* <p>
* This method will handle a file in either Unix or Windows format.
* The position of the last forward or backslash is returned.
* <p>
* The output will be the same irrespective of the machine that the code is running on.
*
* @param filename the filename to find the last path separator in, null returns -1
* @return the index of the last separator character, or -1 if there
* is no such character
*/
public static int indexOfLastSeparator(String filename) {
if (filename == null) {
return -1;
}
int lastUnixPos = filename.lastIndexOf(UNIX_SEPARATOR);
int lastWindowsPos = filename.lastIndexOf(WINDOWS_SEPARATOR);
return Math.max(lastUnixPos, lastWindowsPos);
}
/**
* Returns the index of the last extension separator character, which is a dot.
* <p>
* This method also checks that there is no directory separator after the last dot.
* To do this it uses {@link #indexOfLastSeparator(String)} which will
* handle a file in either Unix or Windows format.
* <p>
* The output will be the same irrespective of the machine that the code is running on.
*
* @param filename the filename to find the last path separator in, null returns -1
* @return the index of the last separator character, or -1 if there
* is no such character
*/
public static int indexOfExtension(String filename) {
if (filename == null) {
return -1;
}
int extensionPos = filename.lastIndexOf(EXTENSION_SEPARATOR);
int lastSeparator = indexOfLastSeparator(filename);
return (lastSeparator > extensionPos ? -1 : extensionPos);
}
//-----------------------------------------------------------------------
/**
* Gets the prefix from a full filename, such as <code>C:/</code>
* or <code>~/</code>.
* <p>
* This method will handle a file in either Unix or Windows format.
* The prefix includes the first slash in the full filename where applicable.
* <pre>
* Windows:
* a\b\c.txt --> "" --> relative
* \a\b\c.txt --> "\" --> current drive absolute
* C:a\b\c.txt --> "C:" --> drive relative
* C:\a\b\c.txt --> "C:\" --> absolute
* \\server\a\b\c.txt --> "\\server\" --> UNC
*
* Unix:
* a/b/c.txt --> "" --> relative
* /a/b/c.txt --> "/" --> absolute
* ~/a/b/c.txt --> "~/" --> current user
* ~ --> "~/" --> current user (slash added)
* ~user/a/b/c.txt --> "~user/" --> named user
* ~user --> "~user/" --> named user (slash added)
* </pre>
* <p>
* The output will be the same irrespective of the machine that the code is running on.
* ie. both Unix and Windows prefixes are matched regardless.
*
* @param filename the filename to query, null returns null
* @return the prefix of the file, null if invalid
*/
public static String getPrefix(String filename) {
if (filename == null) {
return null;
}
int len = getPrefixLength(filename);
if (len < 0) {
return null;
}
if (len > filename.length()) {
return filename + UNIX_SEPARATOR; // we know this only happens for unix
}
return filename.substring(0, len);
}
/**
* Gets the path from a full filename, which excludes the prefix.
* <p>
* This method will handle a file in either Unix or Windows format.
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -