本文主要介绍一下 path 库的使用。

path 库的 pub 仓库地址:path

1. path 库的介绍

path 是针对 Dart 语言设计的一个全面的、跨平台的路径操作库。path 插件提供了操作路径的常用操作:加入、拆分、规范化等。

2. path 库的使用

2.1 添加依赖

  1. dependencies:
  2. path: ^1.8.1

path 的版本号参考:Stable versions of path

2.2 导包

  1. import 'package:path/path.dart' as p;
  2. /// 也可以不使用前缀的方式,直接用全路径的方式导入。本文后面的例子以使用前缀的方式。
  3. import 'package:path/path.dart';

2.3 最常用的函数:join()

path 库最常用方法是顶级函数 join()。join 函数会根据你当前的工作目录和使用的主机平台的路径样式(POSIXWindows,或 URLs)来将给定的路径连接成单个路径,并返回。

  • POSIX 风格的路径使用 /(正斜杠)作为分隔符。绝对路径以 / 开头。适用于 UNIXLinuxMac OS X等。
  • Windows 风格的路径使用 \ (反斜杠)作为分隔符。绝对路径以驱动器号和冒号开头(例如,C:),或者两个反斜杠(\\)作为 UNC 路径。
  • URLs 不是文件系统路径,path 支持它是为了更容易在浏览器中操作 URL 路径。URLs 使用 / (正斜杠)作为分隔符。绝对路径可以以一个协议和可选的主机名(例如。https://dart.dev文件://),也可以在尾部加一个 /

代码片段:

  1. p.join('directory', 'file.txt');

调用 join() 会以当前平台的目录分隔符连接“directory”和“file.txt”。join 函数会返回拼接后的路径 String。

以我使用的 mac 电脑为例子,会使用正斜杠 / 分隔符来连接,如果将 p.join('directory', 'file.txt') 的结果打印出来会得到如下的一个 String:

  1. directory/file.txt

如果你想指定使用某个特定平台的路径分隔符,你可以创建一个 Context 并给指定一个 Style

  1. import 'package:path/path.dart' as p;
  2. String getContextPathString() {
  3. var context = p.Context(style: p.Style.windows);
  4. return context.join('directory', 'file.txt');
  5. }

此时,输出 context.join('directory', 'file.txt') 的结果会得到如下 String:

  1. directory\file.txt

👉 使用 join 的一些规则

1.join() 最多只能接收 8 个参数。

来看看 join 函数的定义就知道了:

  1. /// 使用了位置可选参数来声明 part2 到 part 8 参数
  2. String join(String part1,
  3. [String? part2,
  4. String? part3,
  5. String? part4,
  6. String? part5,
  7. String? part6,
  8. String? part7,
  9. String? part8]) =>
  10. context.join(part1, part2, part3, part4, part5, part6, part7, part8);

2.如果任何 part 参数以路径分隔符结尾,则会被忽略掉

代码片段:

  1. /// 我们在 directory 后面加了一个正斜杠
  2. p.join('directory/', 'to', 'foo');
  3. //// 打印结果为:directory/to/foo

3.如果某个 part 参数使用了绝对路径,那么它之前的 part 参数都将被忽略

代码片段:

  1. /// 我们在第二个参数使用了一个绝对路径 /to
  2. p.join('directory', '/to', 'foo');
  3. /// 打印结果为:/to/foo

2.4 joinAll() 函数

joinAll() 函数的作用和路径的生成规则与 join() 函数是一样的,只是需要的参数不同。

joinAll() 接收一个 Iterable<String> 参数。

代码片段:

  1. p.joinAll(['path', 'to', 'foo']); // 返回路径 'path/to/foo'
  2. p.joinAll(['path/', 'to', 'foo']); // 返回路径 'path/to/foo
  3. p.joinAll(['path', '/to', 'foo']); // 返回路径 '/to/foo'

👉 Tips

对于固定数量的 part 路径,通常使用 join() 函数。

2.5 dirname(String path) 函数

作用:获取最后一个分隔符之前的 path 部分。

代码片段:

  1. p.dirname('path/to/foo.dart'); // 返回 'path/to'
  2. p.dirname('path/to'); // 返回 'path'
  3. /// 末尾的分隔符会被忽略
  4. p.dirname('path/to/'); // 返回 'path'
  5. /// 如果绝对路径且仅包含根目录,则返回根目录
  6. p.dirname('/'); // 返回 '/' (posix)
  7. p.dirname('c:\'); // 返回 'c:\' (windows)
  8. /// 如果相对路径没有目录,则 '.' 被退回
  9. p.dirname('foo'); // 返回 '.'
  10. p.dirname(''); // 返回 '.'

2.6 normalize(String path) 标准化路径

normalize() 通过处理 ... 来简化路径,并且会尽可能地删除多余的路径分隔符。

代码片段:

  1. p.normalize('path/./to/..//file.text'); // 返回 'path/file.txt'

2.7 canonicalize(String path) 规范化路径

如果两个输入路径都指向同一位置时,调用 canonicalize() 会保证返回相同的路径。 与 normalize() 不同,它尽可能返回 绝对路径,并在 Windows 上规范化 ASCII 大小写。

2.8 basename(String path) 函数

作用:获取最后一个分隔符之后的 path 部分。

代码片段:

  1. p.basename('path/to/foo.dart'); // 返回 'foo.dart'
  2. p.basename('path/to'); // 返回 'to'
  3. /// 末尾的分隔符会被忽略
  4. p.basename('path/to/'); // 返回 'to'

2.9 basenameWithoutExtension(String path) 函数

作用:获取最后一个分隔符之后的 path 部分,并且没有任何文件后缀名。

代码片段:

  1. p.basenameWithoutExtension('path/to/foo.dart'); // 返回 'foo'
  2. /// 末尾的分隔符会被忽略
  3. p.basenameWithoutExtension('path/to/foo.dart/'); // 返回 'foo'

2.10 extension(String path, [int level = 1]) 函数

作用:获取 path 的文件扩展名:basename 的最后一部分,包括 . 本身。

代码片段:

  1. p.extension('path/to/foo.dart'); // 返回 '.dart'
  2. p.extension('path/to/foo'); // 返回 ''
  3. p.extension('path.to/foo'); // 返回 ''
  4. p.extension('path/to/foo.dart.js'); // 返回 '.js'
  5. /// 如果文件名以 `.` 开头,则不视为扩展名
  6. p.extension('~/.bashrc'); // 返回 ''
  7. p.extension('~/.notes.txt'); // 返回 '.txt'
  8. /// 可以指定返回包含多个 . 的扩展名
  9. p.extension('foo.bar.dart.js', 2); // 返回 '.dart.js
  10. p.extension('foo.bar.dart.js', 3); // 返回 '.bar.dart.js'
  11. p.extension('path/to/foo.bar.dart.js', 2); // -> '.dart.js'
  12. /// 如果指定的数量超过了总的 . 数,则返回完整的扩展名
  13. p.extension('foo.bar.dart.js', 10); // 返回 '.bar.dart.js'
  14. /// 注意,指定的数量不能为 0,否者会出现 RangeError 错误

2.11 rootPrefix(String path) 函数

作用:如果是绝对路径,则返回 path 的根,如果是相对路径,则返回空字符串。

  1. // Unix
  2. p.rootPrefix('path/to/foo'); // -> ''
  3. p.rootPrefix('/path/to/foo'); // -> '/'
  4. // Windows
  5. p.rootPrefix(r'path\to\foo'); // -> ''
  6. p.rootPrefix(r'C:\path\to\foo'); // -> r'C:\'
  7. p.rootPrefix(r'\\server\share\a\b'); // -> r'\\server\share'
  8. // URL
  9. p.rootPrefix('path/to/foo'); // -> ''
  10. p.rootPrefix('https://dart.dev/path/to/foo');// -> 'https://dart.dev'

2.12 split(String path) 函数

作用:使用当前平台的分隔符对 path 进行拆分。

代码片段:

  1. p.split('path/to/foo'); // 返回 ['path', 'to', 'foo']
  2. /// 拆分前路径不会执行 normalize 操作
  3. p.split('path/../foo'); // 返回 ['path', '..', 'foo']
  4. /// 如果 path 是绝对的,则根目录将是数组中的第一个元素
  5. // Unix
  6. p.split('/path/to/foo'); // 返回 ['/', 'path', 'to', 'foo']
  7. // Windows
  8. p.split(r'C:\path\to\foo'); // 返回 [r'C:\', 'path', 'to', 'foo']
  9. p.split(r'\\server\share\path\to\foo');// 返回 [r'\\server\share', 'foo', 'bar', 'baz']
  10. // Browser
  11. p.split('https://dart.dev/path/to/foo');// 返回 ['https://dart.dev', 'path', 'to', 'foo']

2.13 relative(String path, {String? from}) 函数

作用:尝试将 path 转换为当前目录的等效相对路径。

代码片段:

  1. // Given current directory is /root/path:
  2. p.relative('/root/path/a/b.dart'); // 返回 'a/b.dart'
  3. p.relative('/root/other.dart'); // 返回 '../other.dart'
  4. /// 如果传递了 [from] 参数,则 [path] 相对于该参数
  5. p.relative('/root/path/a/b.dart', from: '/root/path'); // 返回 'a/b.dart'
  6. p.relative('/root/other.dart', from: '/root/path');// 返回 '../other.dart'

2.14 isWithin(String parent, String child)

作用:如果 childparent 下面的路径,则返回 true,否则返回 false

代码片段:

  1. p.isWithin('/root/path', '/root/path/a'); // -> true
  2. p.isWithin('/root/path', '/root/other'); // -> false
  3. p.isWithin('/root/path', '/root/path') // -> false

2.15 equals(String path1, String path2)

作用:如果 path1 指向与 path2 相同的位置,则返回 true,否则 false

代码片段:

  1. path.equals('a/b', 'a/b') -> true

2.16 withoutExtension(String path) 函数

作用:从 path 的最后一部分删除末尾扩展名。

代码片段:

  1. p.withoutExtension('path/to/foo.dart'); // -> 'path/to/foo'

2.17 setExtension(String path, String extension) 函数

作用:将 path 末尾的扩展名设置为 extension 参数的值。如果 path 末尾没有扩展名,会将 extension 的值添加到末尾。

代码片段:

  1. p.setExtension('path/to/foo.dart', '.js') // 返回 'path/to/foo.js'
  2. p.setExtension('path/to/foo.dart.js', '.map')// 返回 'path/to/foo.dart.map'
  3. p.setExtension('path/to/foo', '.js') // 返回 'path/to/foo.js'

2.18 fromUri

作用:返回 uri 表示的路径,可以是 String 或 Uri。

代码片段:

  1. /// 对于 POSIX and Windows styles, [uri] 必须是 `file:` URI。
  2. /// 对于 URL style, 将会把 [uri] 转换为一个 string.
  3. // POSIX
  4. p.fromUri('file:///path/to/foo') // -> '/path/to/foo'
  5. // Windows
  6. p.fromUri('file:///C:/path/to/foo') // -> r'C:\path\to\foo'
  7. // URL
  8. p.fromUri('https://dart.dev/path/to/foo')// -> 'https://dart.dev/path/to/foo'
  9. /// If [uri] is relative, a relative path will be returned.
  10. p.fromUri('path/to/foo'); // -> 'path/to/foo'

2.19 prettyUri

作用:可以传递一个 String 或者 Uri,将返回简洁、易读的 uri。

代码片段:

  1. // POSIX at "/root/path"
  2. p.prettyUri('file:///root/path/a/b.dart'); // -> 'a/b.dart'
  3. p.prettyUri('https://dart.dev/'); // -> 'https://dart.dev'
  4. // Windows at "C:\root\path"
  5. p.prettyUri('file:///C:/root/path/a/b.dart'); // -> r'a\b.dart'
  6. p.prettyUri('https://dart.dev/'); // -> 'https://dart.dev'
  7. // URL at "https://dart.dev/root/path"
  8. p.prettyUri('https://dart.dev/root/path/a/b.dart'); // -> r'a/b.dart'
  9. p.prettyUri('file:///root/path'); // -> 'file:///root/path'