File Paths in C#

The System.IO.Path class provides methods to parse and construct file paths in a way that is portable between operating systems; dir/file on Linux vs. dir\file on Windows, for example.

using System;
using System.IO;

class FilePaths
{
    static void Main()
    {
        // Path.Combine should be used to construct paths in a
        // portable way. It takes any number of arguments
        // and constructs a hierarchical path from them.
        string p = Path.Combine("dir1", "dir2", "filename");
        Console.WriteLine($"p: {p}");

        // You should always use Path.Combine instead of
        // concatenating / or \ manually. In addition
        // to providing portability, Path.Combine will also
        // normalize paths by removing superfluous separators
        // and directory changes.
        Console.WriteLine(Path.Combine("dir1//", "filename"));
        Console.WriteLine(Path.Combine("dir1/../dir1", "filename"));

        // GetDirectoryName and GetFileName can be used to split a path to the
        // directory and the file. Alternatively, you can use
        // Path.GetDirectoryName and Path.GetFileName separately.
        Console.WriteLine($"GetDirectoryName(p): {Path.GetDirectoryName(p)}");
        Console.WriteLine($"GetFileName(p): {Path.GetFileName(p)}");

        // We can check whether a path is absolute.
        Console.WriteLine(Path.IsPathRooted("dir/file"));
        Console.WriteLine(Path.IsPathRooted("/dir/file"));

        string filename = "config.json";

        // Some file names have extensions following a dot. We
        // can split the extension out of such names with GetExtension.
        string ext = Path.GetExtension(filename);
        Console.WriteLine(ext);

        // To find the file's name with the extension removed,
        // use GetFileNameWithoutExtension.
        Console.WriteLine(Path.GetFileNameWithoutExtension(filename));

        // GetRelativePath finds a relative path between a base and a
        // target. It returns the target if the paths are on different
        // drives or a relative path cannot be constructed.
        string rel = Path.GetRelativePath("a/b", "a/b/t/file");
        Console.WriteLine(rel);

        rel = Path.GetRelativePath("a/b", "a/c/t/file");
        Console.WriteLine(rel);
    }
}

To run the program, compile and execute it using the C# compiler:

$ csc FilePaths.cs
$ mono FilePaths.exe
p: dir1\dir2\filename
dir1\filename
dir1\filename
GetDirectoryName(p): dir1\dir2
GetFileName(p): filename
False
True
.json
config
t\file
..\c\t\file

Note that the output may vary slightly depending on the operating system you’re using, particularly for path separators.

In C#, we use the System.IO.Path class to handle file paths in a cross-platform manner. This class provides methods similar to those in the Go filepath package, such as Combine (equivalent to Go’s Join), GetDirectoryName and GetFileName (similar to Go’s Dir and Base), and GetRelativePath (similar to Go’s Rel).

The Path.IsPathRooted method in C# is used to check if a path is absolute, which is equivalent to Go’s filepath.IsAbs. For string operations like trimming the extension, C# provides specific methods like Path.GetFileNameWithoutExtension, eliminating the need for manual string manipulation.

Remember that while the concepts are similar, the exact behavior might differ slightly between Go and C#, especially when dealing with different operating systems.