Cross-Platform File Paths
Fast recall
Quick revision
Core answer
Path.of and resolve instead of joining strings with / or \. Keep stored paths relative when appropriate, normalize only for syntax, and use file-system-aware checks when existence, links, or security boundaries matter.Interview-ready guide
Interview answer
Cross-platform Java code builds paths from path elements instead of joining strings with / or \. Path.of("reports", "2026", "summary.txt") lets the file-system provider use the correct separator, and base.resolve("summary.txt") safely creates a child path.
A relative path depends on a base, often the JVM's current working directory, so an application should resolve important paths against an explicit configured directory. toAbsolutePath() shows the absolute form but does not prove the file exists. normalize() removes redundant . and .. elements without reading the file system, while toRealPath() requires the target to exist and normally resolves symbolic links.
For example, an upload service can start from a controlled uploads directory and resolve a supplied file name below it. normalize().startsWith(base) rejects simple ../ escapes, but it is not complete protection when an attacker can influence symbolic links. Secure code must also restrict names, control the directory, define link behavior, and validate the real parent at the time of opening or creation.
Operating systems can also differ in roots, case sensitivity, and reserved characters. Path separators inside one path are different from separators used in a list such as a classpath. Keep paths as Path objects, resolve them against an explicit base, and convert to strings only for display, configuration, or a protocol that defines its own path format.
Cross-Platform File Paths
Direct Answer
Build cross-platform paths from separate name elements with Path.of and resolve instead of joining strings with / or \. Keep stored paths relative when appropriate, normalize only for syntax, and use file-system-aware checks when existence, links, or security boundaries matter.
Deep Dive & Architecture
Path solves platform-sensitive name construction, but it does not decide whether a requested location is safe. A normalized lexical path can still pass through a symbolic link that leads outside the intended tree. The application needs a separate containment policy based on who controls the parent directories and whether links are allowed.
For an existing target, comparing real paths can resolve links. For a new target, validate an existing real parent, restrict the new filename, and create through a controlled directory. Race-free security can require operating-system or secure-directory primitives rather than a check followed by a later open.
Also keep URL paths separate from file paths: a URL always follows URI syntax and should not be assembled with the host file separator.
Code Example
import java.nio.file.Path;
class CrossPlatformPaths {
static Path reportPath(Path workspace, int year) {
return workspace.resolve(Path.of("reports", String.valueOf(year), "summary.txt"))
.normalize();
}
public static void main(String[] args) {
Path workspace = Path.of(System.getProperty("java.io.tmpdir"), "interview-explainer");
Path report = reportPath(workspace, 2026);
System.out.println(report.endsWith(Path.of("reports", "2026", "summary.txt")));
}
}
Check your understanding
Answer these without looking back at the article.
- What is the difference between normalize and toRealPath?
- Why can startsWith after normalize be insufficient for upload security?
- What is File.pathSeparator used for?
Looking for a structured roadmap?
Every module on this page is also part of the full Java backend interview track.