File paths are represented by strings, but they don’t act like strings. People often manipulate paths by using simple string operations, but this is a mistake. In this short post I’ll justify not treating paths like strings by showing how two ‘simple’ path operations, combining paths and equating paths, do not correspond to the simple string operations I so often see used as if they were equivalent. Perhaps the most common operation performed on paths is combining them. Given a root path and a relative path, return a path that where the relative path is relative to the root path. For example, combining the root path The naive way to do path combining is via string concatenation: The above solution has three problems: A proper path combiner doesn’t have the above problems. The .Net framework actually includes such a method: Path.Combine. Use it. (Perhaps even on hardcoded paths, to avoid any issues related to assuming a particular directory separator character.) Needing to determine if two paths are equivalent (i.e. resolve to the same local file) is not as common an operation as combining, but it still shows up now and then. The naive solution for equating paths is to use string equality: The above code is horribly, horribly wrong. Allow me to list why: If you try to determine path equality via string equality, expect things to go badly when any of those six issues comes into play. Unfortunately, because different use cases require different variants of path equality (Does it make sense for relative paths to be considered equivalent to absolute paths? What sorts of macros are there? Do we care about hard links?), there’s no standard method(s) to equate paths. At least, not that I’m aware of in the languages I use day to day. If you need to compare paths, you’re likely stuck implementing your own utility method. Determine what the semantics should be, and make sure to include tests covering the mentioned issues. Paths are represented by strings, but it can be misleading to think of them as strings. When working with paths you should use methods designed to work on paths, not strings. There are string operations that appear to correspond to path operations, such as combining paths via string concatenation and comparing paths via string equality, but they miss important corner cases. Note that, if you happen to be in a programming language with a structured type for paths, you should consider using that instead of raw strings wherever possible. For example, in Java you can use File or Path and in .Net you can use FileInfo and related classes. — —
Don’t Treat Paths Like Strings
Path Combining is not String Concatenation
C:\ProgramFiles
with the relative path SomeApp\Defaults.dat
gives the resulting path C:\ProgramFiles\SomeApp\Defaults.dat
.string Combine(string root, string relative) {
return root + @"\" + relative; // NO. BAD.
}
C:\test1
and C:\test2
. What should combining these paths do? I see two reasonable interpretations: throw an error, or have the second path being absolute cause the first path to be ignored. Instead of those two possibilities, the naive method returns an invalid path (C:\test1\C:\test2
) that can cause a crash at some future inconvenient time.
Path Equality is not String Equality
bool ArePathsEqual(string path1, string path2) {
return path1 == path2; // Not even CLOSE to correct.
}
Documents\Doc.txt
is equivalent to the path Documents\/\/\/\/\////\\\Doc.txt
.
Documents\Doc.txt
is equivalent to the path Documents\.\..\.\Documents\.\.\.\Doc.txt
.
%AppData%\Defaults.dat
may expand into C:\ProgramData\YourApp\Defaults.dat
and so, in cases where the path will be expanded in that way, you should consider those two paths to be equivalent.
Relative.txt
resolves to the same file as C:\Relative.txt
when the current directory is C:
, but not when the current directory is elsewhere. You need to decide if you want relative and absolute paths to be sometimes equivalent (when the current directory happens to make them match) or never equivalent (since they are affected differently by changing the current directory).
Summary
Discuss on Reddit
Twisted Oak Studios offers consulting and development on high-tech interactive projects. Check out our portfolio, or Give us a shout if you have anything you think some really rad engineers should help you with.
Archive