RFR: 8298318: (fs) APIs for handling filename extensions [v8]
Anthony Vanelverdinghe
duke at openjdk.org
Sat Mar 16 22:23:24 UTC 2024
On Wed, 13 Mar 2024 23:12:50 GMT, Brian Burkhalter <bpb at openjdk.org> wrote:
>> Add to `java.nio.file.Path` a method `getExtension` to retrieve the `Path`'s extension, and companion methods `removeExtension` and `addExtension`.
>
> Brian Burkhalter has updated the pull request incrementally with one additional commit since the last revision:
>
> 8298318: Add parameter checks for withExtension
Thanks for bearing with me and detailing the rationale.
What I still fail to grasp, is why consistent behavior across platforms and providers is a must. This PR demonstrates that there's simply no such thing as *the* definition of file extension and most of the `java.nio.file` APIs already exhibit non-portable behavior in one way or the other: the related `Files::probeContentType` isn't consistent across platforms, most APIs don't allow mixing Paths from different providers, creating a path on UNIX by passing in a Windows path (`Path.of("foo\\bar")`) will give an unexpected result, `Files.copy(zipEntry, extractedFile)` will return `false` for `Files.isHidden(zipEntry)` while it might return `true` for `Files.isHidden(extractedFile)`, ...
On another note, is the intention to specify "if there's no debate possible, we return the file extension. Otherwise, we return the empty string"?
If so, I believe the return type ought to be `Optional<String>`. That way `text` could return `Optional.of("")` whereas `text.` would return `Optional.empty()`. And then I could do `file.getExtension().or(treatEdgeCases)` to treat edge cases as appropriate for my use case.
If not, and the intention really is to specify that neither `.mp3` nor `test.` have a file extension and that
> for an extension to have any significance, there must be a root or base of the file name
then I find this problematic, because this assertion is simply not true: on Windows, extensions are always significant and on UNIX, files with an empty root can't be created due to the "hidden marker"-meaning taking precedence over the "file extension"-meaning. In other words: I'm not aware of any platform where this assertion can be demonstrated to be true.
On a final note, I think the implementation for `1.` in my previous comment is actually a pretty good compromise: it retains the current minimalistic API, ensures consistent behavior across providers (unless overridden of course, but the current API has the same issue), and it allows developers to set their own provider in order to implement the API as desired (e.g. I could implement a provider which, for `Path.of(".mp3")` returns either `mp3` or `""`, depending on whether the file is located on an NTFS filesystem or not). `getExtension` would then just be specified in the same vein as `Files::isHidden` and the invariant would be as generic as possible: `getExtension().equalsIgnoreCase(withoutExtension().withExtension(getExtension()).getExtension())`.
-------------
PR Comment: https://git.openjdk.org/jdk/pull/16226#issuecomment-2000190223
More information about the nio-dev
mailing list