HomeSearch

C# Path Examples

Extract parts of paths with the Path class. Handle file locations in a consistent way.

Path. This path leads somewhere. It goes between trees and buildings. A cloud moves. Sunlight reaches the ground and our direction is clear.

With Path, a class in the .NET Framework, we have built-in methods. This class helps when handling file paths. It is part of System.IO.

GetFileName example. Taken all at once, the Path class might seem complicated and hard to use. But when we decompose it and look at individual methods, it is straightforward.

First: We call Path.GetFileName, a static method, on a path string. It returns just the end part of the path.

C# program that uses GetFileName using System; using System.IO; class Program { static void Main() { string path = @"C:\programs\file.txt"; // Get file name. string filename = Path.GetFileName(path); Console.WriteLine("PATH: {0}", path); Console.WriteLine("FILENAME: {0}", filename); } } Output PATH: C:\programs\file.txt FILENAME: file.txt

File name, no extension. Sometimes we want just the file name part, with no extension included. There is a special method for this purpose—we call it in this program.

Info: We see that the ".doc" part of the file name is removed—so we are left with the string "example" only.

C# program that uses GetFileNameWithoutExtension using System; using System.IO; class Program { static void Main() { string path = @"C:\programs\example.doc"; // Get file name without extension. string filename = Path.GetFileNameWithoutExtension(path); Console.WriteLine("PATH: {0}", path); Console.WriteLine("NO EXTENSION: {0}", filename); } } Output PATH: C:\programs\example.doc NO EXTENSION: example

GetExtension example. What if we want the extension part only, without the rest of the path? The GetExtension method helps here. The leading period is included in the result.Path.GetExtension

Note: GetExtension handles extensions of 4 letters. It also handles the case where a file name has more than one period in it.

Here: This program briefly tests GetExtension. The period is part of the extension string returned.

C# program that uses GetExtension using System; using System.IO; class Program { static void Main() { // ... Path values. string value1 = @"C:\perls\word.txt"; string value2 = @"C:\file.excel.dots.xlsx"; // ... Get extensions. string ext1 = Path.GetExtension(value1); string ext2 = Path.GetExtension(value2); Console.WriteLine(ext1); Console.WriteLine(ext2); } } Output .txt .xlsx

GetPathRoot. The "path root" is the volume name and its trailing separator. For the C drive, we get the value "C:\" in a string. This can be used in Path.Combine to build up full paths.
C# program that gets path root using System; using System.IO; class Program { static void Main() { string path = "C:\\images\\universe.jpg"; // Get path root. string root = Path.GetPathRoot(path); Console.WriteLine("PATH: {0}", path); Console.WriteLine("ROOT: {0}", root); } } Output PATH: C:\images\universe.jpg ROOT: C:\

GetDirectoryName example. We often need to get the directory name from a string path. The root, and the folder name are returned, without a trailing slash.Path.GetDirectoryName
C# program that uses GetDirectoryName using System; using System.IO; class Program { static void Main() { string path = "C:\\images\\universe.jpg"; // Get directory name. string result = Path.GetDirectoryName(path); Console.WriteLine("PATH: {0}", path); Console.WriteLine("DIRECTORY: {0}", result); } } Output PATH: C:\images\universe.jpg DIRECTORY: C:\images

Path syntax. In path literals, we must use two backslashes "\\" unless we use verbatim string syntax. A verbatim string uses the prefix character "@". In it, only one backslash is needed.String Literal
C# program that uses verbatim string using System; class Program { static void Main() { // Verbatim string syntax. string value = @"C:\directory\word.txt"; string value2 = "C:\\directory\\word.txt"; Console.WriteLine("VALUE: {0}", value); Console.WriteLine("VALUE2: {0}", value2); } } Output VALUE: C:\directory\word.txt VALUE2: C:\directory\word.txt

Combine. Sometimes we have 2 or more parts, and want to merge them into a complete path. We can invoke Combine() on the folder "Content\\" with the file name "file.txt."

Info: Path.Combine handles certain cases where we have directory separators in different positions.

Escape: When we have to add the character "\" to a non-verbatim C# string literal, we must use \\ (two backslashes).

Arguments: The arguments to Path.Combine are parts of a path. These can be the volume name, a directory name, or a file name.

C# program that uses Path.Combine using System; using System.IO; class Program { static void Main() { // Combine 2 path parts. string path1 = Path.Combine("Content", "file.txt"); Console.WriteLine("COMBINE: {0}", path1); // Combine handles trailing separator. string path2 = Path.Combine("Content\\", "file.txt"); Console.WriteLine("COMBINE: {0}", path2); // Handle 3 parts. string path3 = Path.Combine("C:\\", "directory", "filename.txt"); Console.WriteLine("COMBINE: {0}", path3); } } Output COMBINE: Content\file.txt COMBINE: Content\file.txt COMBINE: C:\directory\filename.txt

GetRandomFileName. Sometimes programs use random file names. If we need to write a temp file and the path is not important, use Path.GetRandomFileName.Path.GetRandomFileName

Info: We can call GetRandomFileName many times in a loop and get different results each time.

C# program that uses GetRandomFileName using System; using System.IO; class Program { static void Main() { for (int i = 0; i < 5; i++) { // Get random file. string result = Path.GetRandomFileName(); Console.WriteLine("RANDOM: {0}", result); } } } Output RANDOM: idpqamj0.uba RANDOM: otyku52c.qlx RANDOM: e5mxa3p2.4cg RANDOM: auxhuuav.c2j RANDOM: epcjprlz.rwr

GetTempPath. This returns temporary file names. They point to a "Temp" folder in the User folder. This program shows the result of GetTempPath.

Note: GetTempPath() has a separator character on the end. Path.GetDirectoryName meanwhile does not.

Note 2: With Path.Combine, we can reliably concatenate a file name with the temporary path received.

Cache: The result of GetTempPath is usually constant throughout program execution. It is safe to cache it. This eliminates allocations.

C# program that uses GetTempPath using System; using System.IO; class Program { static void Main() { // Get temp path. string temp = Path.GetTempPath(); Console.WriteLine("TEMP PATH: {0}", temp); // Create a temp file path. string combined = Path.Combine(temp, "test.txt"); Console.WriteLine("TEMP FILE: {0}", combined); } } Output TEMP PATH: C:\Users\Sam\AppData\Local\Temp\ TEMP FILE: C:\Users\Sam\AppData\Local\Temp\test.txt

Separators. There are 2 properties for separators. These help us develop code that is understandable. It may be easier to understand the name Path.DirectorySeparatorChar.

Next: We examine these 2 properties in the Visual Studio debugger, and see they are the backslash and the forward slash.

Path.DirectorySeparatorChar result "\\" Path.AltDirectorySeparatorChar result "/"

Invalid chars. A program should expect that invalid characters will be encountered. We need to quickly detect invalid path characters.

So: We can use the Path.GetInvalidFileNameChars and Path.GetInvalidPathChars methods.

Dictionary: We can use the character arrays returned by Path.GetInvalidFileNameChars and Path.GetInvalidPathChars with a Dictionary.

ToDictionary
C# program that gets invalid characters using System; using System.Collections.Generic; using System.IO; using System.Linq; class Program { static void Main() { // First, we build a Dictionary of invalid characters. var dict = GetInvalidFileNameChars(); // Next, we test the dictionary to see if the asterisk (star) is valid. if (dict.ContainsKey('*')) { // This will run. // ... The star is in the Dictionary. Console.WriteLine("* is an invalid char"); } } /// <summary> /// Get a Dictionary of the invalid file name characters. /// </summary> static Dictionary<char, bool> GetInvalidFileNameChars() { // This method uses lambda expressions with ToDictionary. return Path.GetInvalidFileNameChars().ToDictionary(c => c, c => true); } } Output * is an invalid char

ASP.NET. URLs and virtual paths are used in ASP.NET websites. The Path class does not work well for these paths. For each ASP.NET request, there is a Request.PhysicalPath.

And: The Request.PhysicalPath value is a Windows-style path. It works well with the Path class.

Code that tests extensions: C# // // This could be in your Global.asax file or in an ASPX page. // It gets the physical path. // string physical = Request.PhysicalPath; // // Here we see if we are handling an ASPX file. // if (Path.GetExtension(physical) == ".aspx") { // // Get the file name without an extension. // string key = Path.GetFileNameWithoutExtension(physical); }

Benchmark, custom method. We must be careful not to change the functionality too much. Path methods contain steps for special cases. We can remove these branches.

Version 1: This version of the code calls a custom implementation of the Path GetFileNameWithoutExtension method.

Version 2: This code calls the Path method that is built into the .NET Framework. This supports more features.

Result: The custom method is much faster but has slight logic differences. The speed helps when this method is often called.

C# program that benchmarks GetFileNameWithoutExtension using System; using System.Diagnostics; using System.IO; class Program { public static string GetFileNameWithoutExtensionFast(string value) { // Find last available character. // ... This is either last index or last index before last period. int lastIndex = value.Length - 1; for (int i = lastIndex; i >= 1; i--) { if (value[i] == '.') { lastIndex = i - 1; break; } } // Find first available character. // ... Is either first character or first character after closest / // ... or \ character after last index. int firstIndex = 0; for (int i = lastIndex - 1; i >= 0; i--) { switch (value[i]) { case '/': case '\\': { firstIndex = i + 1; goto End; } } } End: // Return substring. return value.Substring(firstIndex, (lastIndex - firstIndex + 1)); } const int _max = 1000000; static void Main() { const string fileName = @"C:\test\ok.txt"; Console.WriteLine("TEST: {0}={1}", GetFileNameWithoutExtensionFast(fileName), Path.GetFileNameWithoutExtension(fileName)); // Version 1: use optimized method. var s1 = Stopwatch.StartNew(); for (int i = 0; i < _max; i++) { if (GetFileNameWithoutExtensionFast(fileName) == null) { return; } } s1.Stop(); // Version 2: use Path method. var s2 = Stopwatch.StartNew(); for (int i = 0; i < _max; i++) { if (Path.GetFileNameWithoutExtension(fileName) == null) { return; } } s2.Stop(); Console.WriteLine(((double)(s1.Elapsed.TotalMilliseconds * 1000000) / _max).ToString("0.00 ns")); Console.WriteLine(((double)(s2.Elapsed.TotalMilliseconds * 1000000) / _max).ToString("0.00 ns")); } } Output TEST: ok=ok 20.68 ns Optimized method 168.30 ns Path method

Change extension. We can change the extension on a path string with ChangeExtension. This is a more graceful approach than using Replace() on the string itself.Path.ChangeExtension

File lists. Often we need lists of files in certain directories. We show how to get recursive lists of files by traversing subdirectories.Directory.GetFilesRecursive File List

Custom methods. Sometimes additional logic is needed. For example, we can store a list of reserved file names. Then we can test to see if a file name is reserved.Reserved FilenamesPath Exists

Uri. This type supports website addresses. It contains helper methods we can use to specify addresses of websites. If a path starts with "http," it is a better idea to use Uri.Uri

A path warning. Path works poorly for URLs or virtual paths in ASP.NET. Web addresses are considered paths, but in the .NET Framework they are URIs. The Uri type is best for them.

A summary. The Path class provides Windows-native path manipulations and tests. It is ideal for file names, directory names, relative paths and file name extensions.
Home
Dot Net Perls
© 2007-2020 Sam Allen. Every person is special and unique. Send bug reports to info@dotnetperls.com.