File Paths in Dart

In Dart, we can use the path package to handle file paths in a way that’s portable across different operating systems. Here’s how we can work with file paths:

import 'dart:io';
import 'package:path/path.dart' as path;

void main() {
  // Join should be used to construct paths in a portable way.
  // It takes any number of arguments and constructs a hierarchical path from them.
  var p = path.join('dir1', 'dir2', 'filename');
  print('p: $p');

  // You should always use join instead of concatenating '/'s or '\'s manually.
  // In addition to providing portability, join will also normalize paths
  // by removing superfluous separators and directory changes.
  print(path.join('dir1//', 'filename'));
  print(path.join('dir1/../dir1', 'filename'));

  // dirname and basename can be used to split a path to the directory and the file.
  print('dirname(p): ${path.dirname(p)}');
  print('basename(p): ${path.basename(p)}');

  // We can check whether a path is absolute.
  print(path.isAbsolute('dir/file'));
  print(path.isAbsolute('/dir/file'));

  var filename = 'config.json';

  // Some file names have extensions following a dot.
  // We can split the extension out of such names with extension.
  var ext = path.extension(filename);
  print(ext);

  // To find the file's name with the extension removed,
  // use basenameWithoutExtension.
  print(path.basenameWithoutExtension(filename));

  // relative finds a relative path between a base and a target.
  // It returns null if the target cannot be made relative to base.
  var rel = path.relative('a/b/t/file', from: 'a/b');
  print(rel);

  rel = path.relative('a/c/t/file', from: 'a/b');
  print(rel);
}

To run this program, save it as file_paths.dart and use the dart command:

$ dart file_paths.dart
p: dir1/dir2/filename
dir1/filename
dir1/filename
dirname(p): dir1/dir2
basename(p): filename
false
true
.json
config
t/file
../c/t/file

In this Dart example:

  1. We use the path package, which provides similar functionality to Go’s filepath package.

  2. The join function is used to construct paths in a portable way.

  3. dirname and basename are used to split a path into directory and file components.

  4. isAbsolute checks if a path is absolute.

  5. extension extracts the file extension.

  6. basenameWithoutExtension gets the file name without the extension.

  7. relative finds a relative path between two paths.

Note that Dart’s path package handles paths slightly differently from Go’s filepath package, but the core concepts are similar. Always use these functions instead of manually manipulating path strings to ensure portability across different operating systems.