Dot Net Perls

Path and System.IO Guide - C#

by Sam Allen

Problem

Paths are complicated. Windows uses different directory separators than other platforms. In C#, you have to escape the \ character as \\, making the syntax hard. Sometimes you just want the filename, and sometimes just the extension.

Solution: C#

Microsoft has thought of this problem already and the Path static class is ideal for our use. Access it by adding "using System.IO;" at the top of your class. Here I answer questions about the Path class and how to use it.

How can I get the filename from a path?

By calling Path.GetFileName(). This will return the filename at the end of the path, along with the extension (such as .doc or .exe). There is also a method to just get the extension, and one just to get the name with no extension.

Some example output

What I show here is a table of results from the methods Path.GetFileName(), Path.GetFileNameWithoutExtension(), and Path.GetDirectoryName(). After the table there's some code and more discussion.

InputPath.GetFileNamePath.GetFileName
WithoutExtension
Path.GetDirectoryName
cat.aspxcat.aspxcat
really-long-page.aspxreally-long-page.aspxreally-long-page
test.aspxtest.aspxtest
invalid-pageinvalid-pageinvalid-page
Content/Rat.aspxRat.aspxRatContent
http://dotnetperls.com/
Cat/Mouse.aspx
Mouse.aspxMousehttp:\dotnetperls.com\Cat
C:\Windows\File.txtFile.txtFileC:\Windows
C:\Word-2007.docxWord-2007.docxWord-2007C:\

How can I call Path methods?

Path is a static class, which means you don't ever need to write "new Path()". Instead, you can simply type Path.GetFileName(), for example. This next example shows how I generated the above table.

//
// using System.IO;
// using System.Diagnostics;
//
string[] pages = new string[]
{
    "cat.aspx",
    "really-long-page.aspx",
    "test.aspx",
    "invalid-page",
    "something-else.aspx",
    "Content/Rat.aspx",
    "http://dotnetperls.com/Cat/Mouse.aspx",
    "C:\\Windows\\File.txt",
    "C:\\Word-2007.docx"
};
foreach (string page in pages)
{
    string name = Path.GetFileName(page);
    string nameKey = Path.GetFileNameWithoutExtension(page);
    string directory = Path.GetDirectoryName(page);
    //
    // Display strings
    //
    Debug.WriteLine(page + "|" + name + "|" + nameKey + "|" + directory);
}

What's important here?

Path.GetFileNameWithoutExtension will return the entire file name if there's no extension on the file. Path.GetDirectoryName returns the entire string except the file name and the slash before it.

Not for URLs. Look at the table above where the directory name of the URL (http://dotnetperls.com/Cat) is received. The slashes are reversed into Windows-style slashes. This is not desirable with virtual paths or URLs.

Directory names. The drive letter such as C:\ is part of the directory name. Windows directories include the drive letter along with the entire folder name. Again, they don't include the trailing slash \.

What about the extensions?

Extensions include the period (.) before the three letters. So, in the above array, the extensions would be: ".aspx" ".txt" or ".docx". To get the extension of the file from the path, use Path.GetExtension(value).

Combine your paths

Path.Combine is a useful method but it is not psychic. It can't figure out what you want if what it receives is confusing. However, different inputs can yield the same result path. Here's a screen where we combine the folder "Content\\" with the file name "file.txt".

What do we see? The screenshot is of what values Path.Combine produced. It shows that the following two lines of code produce the same result.

string a = Path.Combine("Content", "file.txt");
//
// a = "Content\\file.txt"
//
string b = Path.Combine("Content\\", "file.txt");
//
// b = "Content\\file.txt"
//

Escape your slashes

The title "escape your slashes" sounds like a horror movie, but what it really says is that to add the char \ to your C# code, you must use \\ (two backslashes). That's because C# uses the backslash to escape characters, so you must escape it also.

Using Path class in ASP.NET

The Path class doesn't work well for URLs or virtual paths, but it is still very useful in ASP.NET websites. For each request in your ASP.NET site, there is a Request.PhysicalPath. That's a Windows-style path that works great with the Path class.

//
// This could be in Global.asax or in an ASPX page.
// Get physical path.
//
string physical = Request.PhysicalPath;
//
// See if we are handling an ASPX file.
//
if (Path.GetExtension(physical) == ".aspx")
{
    //
    // Get file name without extension
    //
    string key = Path.GetFileNameWithoutExtension(physical);
    //
    // etc.
    //
}

Random file names

Random file names are very useful for many programs. If you need to write a temp file or log and you don't care about the path, use Path.GetRandomFileName(). I use this for random strings, too, but that isn't its primary purpose. Here's the random string it yielded just now: zd4xcjmo.u4p.

Separator characters

Path also includes two properties for separators. These are good for creating code that is easy to understand, as it is easier to read Path.DirectorySeparatorChar instead of \\ (at least for many humans). I looked these two properties in the debugger.

PropertyChar value
Path.DirectorySeparatorChar'\\'
Path.AltDirectorySeparatorChar'/'

Temporary file names

Here are methods for getting temporary file names. I haven't used these at all, but in looking at them in the debugger, they point to a "Temp" folder in your User folder (on Windows Vista). Here are what Visual Studio 2008's debugger says my temp file names are. Note that GetTempPath() has a separator character on the end, unlike Path.GetDirectoryName's return value.

Path methodExample valueComment
Path.GetTempFileName()"C:\\Users\\allensamuel\\AppData\\Local\\Temp\\tmpC1D0.tmp"Ends with ".tmp"
Path.GetTempPath()"C:\\Users\\allensamuel\\AppData\\Local\\Temp\\"Ends with \\

Invalid characters in paths and file names

When accepting input from your user, your program must expect that invalid characters will be entered. For example, your program has a custom file name dialog. You want to quickly detect invalid path characters. You can use Path.GetInvalidFileNameChars() and Path.GetInvalidPathChars().

Invalid char Dictionary. Here I show how you can augment the character arrays of invalid characters returned by .NET in the Path.GetInvalidFileNameChars() and Path.GetInvalidPathChars() methods. Use LINQ and create Dictionaries. This will ensure constant O(1) lookup time.

void Example()
{
    //
    // Build a Dictionary of invalid characters.
    //
    var dict = GetInvalidFileNameDictionary();
    //
    // Test the dictionary to see if the asterisk (star) is valid. (It's not.)
    //
    if (dict.ContainsKey('*'))
    {
        //
        // This will run, because the star is in the Dictionary.
        //
        Debug.WriteLine("* is an invalid char");
    }
}

Dictionary<char, bool> GetInvalidFileNameDictionary()
{
    //
    // Read about ToDictionary.
    //
    return Path.GetInvalidFileNameChars().ToDictionary(c => c, c => true);
}

There's more about Path

Path is a powerful class, and other abilities it has include changing a file name's extension, determining whether the path is "rooted"--meaning whether it is relative or absolute. You can also get information about the volume (which is your hard drive usually).

Summary: finding paths in C#

What to use Path for. Use path for Windows-native path manipulations and tests. It is ideal for file names, directory names, relative paths, file name extensions, and invalid character testing. It is good for use with the PhysicalPath in ASP.NET.

What it's bad with. Don't use Path for URLs or virtual paths in ASP.NET. Path has inconsistencies with directory names (sometimes they contains an ending separator). It doesn't have lookup tables for invalid characters, so you need to use the array or a custom Dictionary.

Dot Net Perls
About
Sitemap
Source code
RSS
File I/O
Excel Interop Use
Using StreamReader
Recursive File and Directory List
ReadLine for Reading File Into List
File Handling
Recent
Pi
NGEN Installer Class
List Element Equality
DateTime Tips and Tricks
Remove HTML Tags From String
© 2008 Sam Allen. All rights reserved.