You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@commons.apache.org by sc...@apache.org on 2004/12/04 20:28:40 UTC
cvs commit: jakarta-commons/io/src/java/org/apache/commons/io FilenameUtils.java
scolebourne 2004/12/04 11:28:40
Modified: io/src/test/org/apache/commons/io FilenameUtilsTestCase.java
io/src/java/org/apache/commons/io FilenameUtils.java
Log:
Add equals methods, document Unix/Windows behaviour
Revision Changes Path
1.23 +23 -1 jakarta-commons/io/src/test/org/apache/commons/io/FilenameUtilsTestCase.java
Index: FilenameUtilsTestCase.java
===================================================================
RCS file: /home/cvs/jakarta-commons/io/src/test/org/apache/commons/io/FilenameUtilsTestCase.java,v
retrieving revision 1.22
retrieving revision 1.23
diff -u -r1.22 -r1.23
--- FilenameUtilsTestCase.java 27 Nov 2004 17:00:51 -0000 1.22
+++ FilenameUtilsTestCase.java 4 Dec 2004 19:28:40 -0000 1.23
@@ -451,6 +451,28 @@
}
//-----------------------------------------------------------------------
+ public void testEquals() {
+ assertEquals(true, FilenameUtils.equals(null, null));
+ assertEquals(false, FilenameUtils.equals(null, ""));
+ assertEquals(false, FilenameUtils.equals("", null));
+ assertEquals(true, FilenameUtils.equals("", ""));
+ assertEquals(true, FilenameUtils.equals("file.txt", "file.txt"));
+ assertEquals(WINDOWS, FilenameUtils.equals("file.txt", "FILE.TXT"));
+ assertEquals(false, FilenameUtils.equals("a\\b\\file.txt", "a/b/file.txt"));
+ }
+
+ public void testEqualsNormalized() {
+ assertEquals(true, FilenameUtils.equalsNormalized(null, null));
+ assertEquals(false, FilenameUtils.equalsNormalized(null, ""));
+ assertEquals(false, FilenameUtils.equalsNormalized("", null));
+ assertEquals(true, FilenameUtils.equalsNormalized("", ""));
+ assertEquals(true, FilenameUtils.equalsNormalized("file.txt", "file.txt"));
+ assertEquals(WINDOWS, FilenameUtils.equalsNormalized("file.txt", "FILE.TXT"));
+ assertEquals(true, FilenameUtils.equalsNormalized("a\\b\\file.txt", "a/b/file.txt"));
+ assertEquals(true, FilenameUtils.equalsNormalized("a\\b\\", "a/b"));
+ }
+
+ //-----------------------------------------------------------------------
public void testIsExtension() {
assertEquals(false, FilenameUtils.isExtension(null, (String) null));
assertEquals(false, FilenameUtils.isExtension("file.txt", (String) null));
1.31 +134 -26 jakarta-commons/io/src/java/org/apache/commons/io/FilenameUtils.java
Index: FilenameUtils.java
===================================================================
RCS file: /home/cvs/jakarta-commons/io/src/java/org/apache/commons/io/FilenameUtils.java,v
retrieving revision 1.30
retrieving revision 1.31
diff -u -r1.30 -r1.31
--- FilenameUtils.java 27 Nov 2004 17:00:51 -0000 1.30
+++ FilenameUtils.java 4 Dec 2004 19:28:40 -0000 1.31
@@ -22,6 +22,16 @@
/**
* Utility class that provides methods to manipulate filenames and filepaths.
* <p>
+ * When dealing with filenames you can hit problems when moving from a Windows
+ * based development machine to a Unix based production machine.
+ * This class aims to help avoid those problems.
+ * <p>
+ * Most methods on this class are designed to work the same on both Unix and Windows.
+ * Both separators (forward and back) are recognised, and both sets of prefixes.
+ * The comparison methods do differ by machine however, comparing case insensitive
+ * on Windows and case sensitive on Unix.
+ * See the javadoc of each method for details.
+ * <p>
* This class defines six components within a filename (example C:\dev\project\file.txt):
* <ul>
* <li>the prefix - C:\</li>
@@ -31,7 +41,9 @@
* <li>the base name - file</li>
* <li>the extension - txt</li>
* </ul>
- * The class only supports Unix and Windows style names. Prefixes are matched as follows:
+ * Note that the path of a directory is the parent directory.
+ * <p>
+ * This class only supports Unix and Windows style names. Prefixes are matched as follows:
* <pre>
* Windows style:
* a\b\c.txt --> "" --> relative
@@ -45,6 +57,8 @@
* ~/a/b/c.txt --> "~/" --> current user relative
* ~user/a/b/c.txt --> "~user/" --> named user relative
* </pre>
+ * Both prefix styles are matched always, irrespective of the machine that you are
+ * currently running on.
*
* </p>
* <h3>Origin of code</h3>
@@ -133,6 +147,9 @@
* A double dot will cause that path segment and the one before to be removed.
* If the double dot has no parent path segment to work with, <code>null</code>
* is returned.
+ * <p>
+ * The output will be the same on both Unix and Windows except
+ * for the separator character.
* <pre>
* /foo// --> /foo
* /foo/./ --> /foo
@@ -151,7 +168,7 @@
* ~/foo/../bar --> ~/bar
* ~/../bar --> null
* </pre>
- * (Note the file separator returned will be correct for windows/unix)
+ * (Note the file separator returned will be correct for Windows/Unix)
*
* @param filename the filename to normalize, null returns null
* @return the normalized String, or null if invalid
@@ -232,7 +249,7 @@
}
/**
- * Concatenates two paths using normal command line style rules.
+ * Concatenates a filename to a base path using normal command line style rules.
* <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)},
@@ -241,43 +258,47 @@
* If <code>pathToAdd</code> is absolute (has a 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/a + bar --> /foo/a/bar
- * /foo/c.txt + bar --> /foo/c.txt/bar
* /foo/ + ../bar --> /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 first parameter must be a path. If it ends with a name, then
+ * (!) 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 pathToAdd path the second path to attach to the first
+ * @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 pathToAdd) {
- int prefix = getPrefixLength(pathToAdd);
+ public static String concat(String basePath, String fullFilenameToAdd) {
+ int prefix = getPrefixLength(fullFilenameToAdd);
if (prefix < 0) {
return null;
}
if (prefix > 0) {
- return normalize(pathToAdd);
+ return normalize(fullFilenameToAdd);
}
if (basePath == null) {
return null;
}
int len = basePath.length();
if (len == 0) {
- return normalize(pathToAdd);
+ return normalize(fullFilenameToAdd);
}
char ch = basePath.charAt(len - 1);
if (isSeparator(basePath.charAt(len - 1))) {
- return normalize(basePath + pathToAdd);
+ return normalize(basePath + fullFilenameToAdd);
} else {
- return normalize(basePath + '/' + pathToAdd);
+ return normalize(basePath + '/' + fullFilenameToAdd);
}
}
@@ -344,8 +365,9 @@
* ~/a/b/c.txt --> "~/" --> current user relative
* ~user/a/b/c.txt --> "~user/" --> named user relative
* </pre>
- * Both sets of prefixes will be matched regardless of the system
- * on which the code runs.
+ * <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
@@ -406,6 +428,8 @@
* <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
@@ -426,6 +450,8 @@
* 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
@@ -459,6 +485,9 @@
* ~/a/b/c.txt --> "~/" --> current user relative
* ~user/a/b/c.txt --> "~user/" --> named user relative
* </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
@@ -476,6 +505,7 @@
/**
* Gets the path from a full filename, which excludes the prefix.
+ * The path of a directory is the parent directory.
* <p>
* This method will handle a file in either Unix or Windows format.
* The text before the last forward or backslash is returned.
@@ -486,6 +516,8 @@
* a/b/c --> a/b
* a/b/c/ --> a/b/c
* </pre>
+ * <p>
+ * The output will be the same irrespective of the machine that the code is running on.
*
* @param filename the filename to query, null returns null
* @return the path of the file, an empty string if none exists, null if invalid
@@ -508,6 +540,7 @@
/**
* Gets the full path from a full filename, which is the prefix + path.
+ * The path of a directory is the parent directory.
* <p>
* This method will handle a file in either Unix or Windows format.
* The text before the last forward or backslash is returned.
@@ -518,6 +551,8 @@
* a/b/c --> a/b
* a/b/c/ --> a/b/c
* </pre>
+ * <p>
+ * The output will be the same irrespective of the machine that the code is running on.
*
* @param filename the filename to query, null returns null
* @return the path of the file, an empty string if none exists, null if invalid
@@ -549,6 +584,8 @@
* a/b/c --> c
* a/b/c/ --> ""
* </pre>
+ * <p>
+ * The output will be the same irrespective of the machine that the code is running on.
*
* @param filename the filename to query, null returns null
* @return the name of the file without the path, or an empty string if none exists
@@ -572,6 +609,8 @@
* a/b/c --> c
* a/b/c/ --> ""
* </pre>
+ * <p>
+ * The output will be the same irrespective of the machine that the code is running on.
*
* @param filename the filename to query, null returns null
* @return the name of the file without the path, or an empty string if none exists
@@ -591,6 +630,8 @@
* a/b.txt/c --> ""
* a/b/c --> ""
* </pre>
+ * <p>
+ * The output will be the same irrespective of the machine that the code is running on.
*
* @param filename the filename to retrieve the extension of.
* @return the extension of the file or an empty string if none exists.
@@ -615,10 +656,12 @@
* There must be no directory separator after the dot.
* <pre>
* foo.txt --> foo
- * a\b\c.jpg --> a\b\c
- * a\b\c --> a\b\c
- * a.b\c --> a.b\c
+ * a\b\c.jpg --> a\b\c
+ * a\b\c --> a\b\c
+ * a.b\c --> a.b\c
* </pre>
+ * <p>
+ * The output will be the same irrespective of the machine that the code is running on.
*
* @param filename the filename to query, null returns null
* @return the filename minus the extension
@@ -637,7 +680,60 @@
//-----------------------------------------------------------------------
/**
- * Checks whether the extension of the filename is that specified.
+ * Checks whether two filenames are equal using the case rules of the system.
+ * <p>
+ * No processing is performed on the filenames other than comparison.
+ * The check is case sensitive on Unix and case insensitive on Windows.
+ *
+ * @param filename1 the first filename to query, may be null
+ * @param filename2 the second filename to query, may be null
+ * @return true if the filenames are equal, null equals null
+ */
+ public static boolean equals(String filename1, String filename2) {
+ if (filename1 == filename2) {
+ return true;
+ }
+ if (filename1 == null || filename2 == null) {
+ return false;
+ }
+ if (SYSTEM_SEPARATOR == WINDOWS_SEPARATOR) {
+ return filename1.equalsIgnoreCase(filename2);
+ } else {
+ return filename1.equals(filename2);
+ }
+ }
+
+ /**
+ * Checks whether two filenames are equal after both have been normalized
+ * and using the case rules of the system.
+ * <p>
+ * Both filenames are first passed to {@link #normalize(String)}.
+ * The check is then performed case sensitive on Unix and case insensitive on Windows.
+ *
+ * @param filename1 the first filename to query, may be null
+ * @param filename2 the second filename to query, may be null
+ * @return true if the filenames are equal, null equals null
+ */
+ public static boolean equalsNormalized(String filename1, String filename2) {
+ if (filename1 == filename2) {
+ return true;
+ }
+ if (filename1 == null || filename2 == null) {
+ return false;
+ }
+ filename1 = normalize(filename1);
+ filename2 = normalize(filename2);
+ if (SYSTEM_SEPARATOR == WINDOWS_SEPARATOR) {
+ return filename1.equalsIgnoreCase(filename2);
+ } else {
+ return filename1.equals(filename2);
+ }
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Checks whether the extension of the filename is that specified
+ * using the case rules of the system.
* <p>
* This method obtains the extension as the textual part of the filename
* after the last dot. There must be no directory separator after the dot.
@@ -663,7 +759,8 @@
}
/**
- * Checks whether the extension of the filename is one of those specified.
+ * Checks whether the extension of the filename is one of those specified
+ * using the case rules of the system.
* <p>
* This method obtains the extension as the textual part of the filename
* after the last dot. There must be no directory separator after the dot.
@@ -698,7 +795,8 @@
}
/**
- * Checks whether the extension of the filename is one of those specified.
+ * Checks whether the extension of the filename is one of those specified
+ * using the case rules of the system.
* <p>
* This method obtains the extension as the textual part of the filename
* after the last dot. There must be no directory separator after the dot.
@@ -721,15 +819,25 @@
//-----------------------------------------------------------------------
/**
- * See if a particular piece of text, often a filename,
- * matches to a specified wildcard, as seen on DOS/UNIX command lines.
+ * Checks a filename to see if it matches the specified wildcard matcher.
+ * <p>
+ * The wildcard matcher uses the characters '?' and '*' to represent a
+ * single or multiple wildcard characters.
+ * This is the same as often found on Dos/Unix command lines.
+ * <pre>
+ * wildcardMatch("c.txt", "*.txt") --> true
+ * wildcardMatch("c.txt", "*.jpg") --> false
+ * wildcardMatch("a/b/c.txt", "a/b/*") --> true
+ * wildcardMatch("c.txt", "*.???") --> true
+ * wildcardMatch("c.txt", "*.????") --> false
+ * </pre>
*
* @param filename the filename to match on
- * @param wildcard the wildcard string to match against
+ * @param wildcardMatcher the wildcard string to match against
* @return true if the filename matches the wilcard string
*/
- public static boolean wildcardMatch(String filename, String wildcard) {
- String[] wcs = splitOnTokens(wildcard);
+ public static boolean wildcardMatch(String filename, String wildcardMatcher) {
+ String[] wcs = splitOnTokens(wildcardMatcher);
int textIdx = 0;
int wcsIdx = 0;
---------------------------------------------------------------------
To unsubscribe, e-mail: commons-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: commons-dev-help@jakarta.apache.org