I'm currently working with some code involving saving a file to a user-defined file. If the user passes in a filename with no extension, the code autodetects the extension based on the file type (stored internally).
However, I'm having a hard time determining whether the filename passed to the code has an extension or not. I'm using Path.HasExtension(filename)
and Path.GetExtension(filename)
but it seems to be exhibiting strange behavior:
File.EXT
=> .EXT
is the extension. This is fine.
This Is A File.EXT
=> .EXT
is the extension. This is also fine.
This Is A File. Not An Extension
=> . Not An Extension
is the extension. However, I would think of this as a file without an extension. Windows thinks so too when I create a file with this name (creating a file with an unrecognized extension causes windows to call it a EXTENSIONNAME File
, whereas files without an extension such as this one are just called File
).
This Is A File.Not An Extension
=> .Not An Extension
is the extension. Same problem as above.
Also note that this same behavior is evident in Path.GetFileNameWithoutExtension(filename)
(e.g. it reports the filename without extension on the last two examples to be just This Is A File
).
So what I'm taking from this is that .NET and Windows differ on what they think of as an extension.
The Question: I'm wondering if it's OK for me to implement code such as this:
if(!Path.HasExtension(filename) || Path.GetExtension(filename).Contains(" ")) {...}
since that would pull my code's definition of a proper extension more in line with how Windows treats things. Or is there something I'm missing here which explicitly says I must allow spaces in my extensions?
I've searched and found this slightly similar question, but the documents linked therein only specify that it's not recommended to end the extension with a space/period -- they say nothing about spaces within the extension.
What makes a valid file name extension? A file name extension is often between one and three characters and is always at the end of the file name, starting with a period. Some programs also support file extensions that are more than three characters. For example, all the latest versions of Microsoft Word support .
Windows file names have two parts separated by a period: first, the file name, and second, a three- or four-character extension that defines the file type. In expenses. xlsx, for example, the first part of the file name is expenses and the extension is xlsx.
Some extensions are only two letters, like the . py extension used for Python scripts, and some have four letters, such as . xlsx, but we still tend to refer to extensions as "three letter extensions" even though some extensions are four letters, two letters or even a single letter.
The extension on a filename in Windows is purely a convention. The GetExtension
and HasExtension
methods only look for a dot in the filename and act accordingly. You are free to put spaces anywhere you like within the filename (including the extension).
When you say "Windows thinks so too", it's really just some code in Explorer that tries to parse out extensions, and it simply uses a slightly different algorithm than .NET.
How the filesystem handles names and how the Windows shell (i.e. Explorer) handles file names are two completely different beasts.
The filesystem doesn't care about spaces, dots or anything else -- to it, the filename is just one opaque string (with some restrictions on allowed characters). The name/extension separation is just a made-up convention. The shell, on the other hand, is free to make up its own interpretation of what an extension is because its purpose is not to store and retrieve file information but rather to provide the user with a better experience. So don't go looking there for answers.
I would suggest going with what the System.IO
methods return (because following the convention is good), but you can do whatever you like in your code if there's a good reason for it.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With