Skip to content

Commit

Permalink
Add PathUtils.getExtension(Path)
Browse files Browse the repository at this point in the history
  • Loading branch information
garydgregory committed Dec 23, 2023
1 parent b059cd3 commit ce52198
Show file tree
Hide file tree
Showing 3 changed files with 53 additions and 0 deletions.
1 change: 1 addition & 0 deletions src/changes/changes.xml
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ The <action> type attribute can be add,update,fix,remove.
<action dev="ggregory" type="add" due-to="Gary Gregory">Add FileTimes.isUnixTime(long).</action>
<action dev="ggregory" type="add" due-to="Gary Gregory">Add FileTimes.toUnixTime(FileTime).</action>
<action dev="ggregory" type="add" due-to="Gary Gregory">Add BrokenInputStream.Builder.</action>
<action dev="ggregory" type="add" due-to="Gary Gregory">Add PathUtils.getExtension(Path).</action>
<!-- UPDATE -->
<action dev="ggregory" type="fix" due-to="Gary Gregory">Bump commons.bytebuddy.version from 1.14.10 to 1.14.11 #534.</action>
</release>
Expand Down
26 changes: 26 additions & 0 deletions src/main/java/org/apache/commons/io/file/PathUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -867,6 +867,32 @@ public static DosFileAttributeView getDosFileAttributeView(final Path path, fina
return Files.getFileAttributeView(path, DosFileAttributeView.class, options);
}

/**
* Gets the extension of a Path.
* <p>
* This method returns the textual part of the Path after the last dot.
* </p>
* <pre>
* foo.txt --&gt; "txt"
* a/b/c.jpg --&gt; "jpg"
* a/b.txt/c --&gt; ""
* a/b/c --&gt; ""
* </pre>
* <p>
* The output will be the same irrespective of the machine that the code is running on.
* </p>
* <p>
*
* @param path the path to query.
* @return the extension of the file or an empty string if none exists or {@code null}
* if the fileName is {@code null}.
* @since 2.16.0
*/
public static String getExtension(final Path path) {
final String fileName = getFileNameString(path);
return fileName != null ? FilenameUtils.getExtension(fileName) : null;
}

/**
* Gets the Path's file name and apply the given function if the file name is non-null.
*
Expand Down
26 changes: 26 additions & 0 deletions src/test/java/org/apache/commons/io/file/PathUtilsTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,32 @@ public void testCreateDirectoriesSymlinkClashing() throws IOException {
assertEquals(symlinkedDir, PathUtils.createParentDirectories(symlinkedDir.resolve("child")));
}

@Test
public void testGetExtension() {
assertNull(PathUtils.getExtension(null));
assertEquals("ext", PathUtils.getExtension(Paths.get("file.ext")));
assertEquals("", PathUtils.getExtension(Paths.get("README")));
assertEquals("com", PathUtils.getExtension(Paths.get("domain.dot.com")));
assertEquals("jpeg", PathUtils.getExtension(Paths.get("image.jpeg")));
assertEquals("", PathUtils.getExtension(Paths.get("a.b/c")));
assertEquals("txt", PathUtils.getExtension(Paths.get("a.b/c.txt")));
assertEquals("", PathUtils.getExtension(Paths.get("a/b/c")));
assertEquals("", PathUtils.getExtension(Paths.get("a.b\\c")));
assertEquals("txt", PathUtils.getExtension(Paths.get("a.b\\c.txt")));
assertEquals("", PathUtils.getExtension(Paths.get("a\\b\\c")));
assertEquals("", PathUtils.getExtension(Paths.get("C:\\temp\\foo.bar\\README")));
assertEquals("ext", PathUtils.getExtension(Paths.get("../filename.ext")));

if (File.separatorChar == '\\') {
// Special case handling for NTFS ADS names
final IllegalArgumentException e = assertThrows(IllegalArgumentException.class, () -> PathUtils.getExtension(Paths.get("foo.exe:bar.txt")));
assertEquals("NTFS ADS separator (':') in file name is forbidden.", e.getMessage());
} else {
// Upwards compatibility:
assertEquals("txt", PathUtils.getExtension(Paths.get("foo.exe:bar.txt")));
}
}

@Test
public void testGetFileName() {
assertNull(PathUtils.getFileName(null, null));
Expand Down

0 comments on commit ce52198

Please sign in to comment.