• 文件系统操作
    • 参见:

    文件系统操作

    std::io::fs 模块包含几个处理文件系统的函数。

    1. use std::fs;
    2. use std::fs::{File, OpenOptions};
    3. use std::io;
    4. use std::io::prelude::*;
    5. use std::os::unix;
    6. use std::path::Path;
    7. // `% cat path` 的简单实现
    8. fn cat(path: &Path) -> io::Result<String> {
    9. let mut f = try!(File::open(path));
    10. let mut s = String::new();
    11. match f.read_to_string(&mut s) {
    12. Ok(_) => Ok(s),
    13. Err(e) => Err(e),
    14. }
    15. }
    16. // `% echo s > path` 的简单实现
    17. fn echo(s: &str, path: &Path) -> io::Result<()> {
    18. let mut f = try!(File::create(path));
    19. f.write_all(s.as_bytes())
    20. }
    21. // `% touch path`(忽略已存在文件)的简单实现
    22. fn touch(path: &Path) -> io::Result<()> {
    23. match OpenOptions::new().create(true).write(true).open(path) {
    24. Ok(_) => Ok(()),
    25. Err(e) => Err(e),
    26. }
    27. }
    28. fn main() {
    29. println!("`mkdir a`");
    30. // 创建一个目录,返回 `io::Result<()>`
    31. match fs::create_dir("a") {
    32. Err(why) => println!("! {:?}", why.kind()),
    33. Ok(_) => {},
    34. }
    35. println!("`echo hello > a/b.txt`");
    36. // 前面的匹配可以用 `unwrap_or_else` 方法简化
    37. echo("hello", &Path::new("a/b.txt")).unwrap_or_else(|why| {
    38. println!("! {:?}", why.kind());
    39. });
    40. println!("`mkdir -p a/c/d`");
    41. // 递归创建一个目录,返回 `io::Result<()>`
    42. fs::create_dir_all("a/c/d").unwrap_or_else(|why| {
    43. println!("! {:?}", why.kind());
    44. });
    45. println!("`touch a/c/e.txt`");
    46. touch(&Path::new("a/c/e.txt")).unwrap_or_else(|why| {
    47. println!("! {:?}", why.kind());
    48. });
    49. println!("`ln -s ../b.txt a/c/b.txt`");
    50. // 创建一个符号链接,返回 `io::Resutl<()>`
    51. if cfg!(target_family = "unix") {
    52. unix::fs::symlink("../b.txt", "a/c/b.txt").unwrap_or_else(|why| {
    53. println!("! {:?}", why.kind());
    54. });
    55. }
    56. println!("`cat a/c/b.txt`");
    57. match cat(&Path::new("a/c/b.txt")) {
    58. Err(why) => println!("! {:?}", why.kind()),
    59. Ok(s) => println!("> {}", s),
    60. }
    61. println!("`ls a`");
    62. // 读取目录的内容,返回 `io::Result<Vec<Path>>`
    63. match fs::read_dir("a") {
    64. Err(why) => println!("! {:?}", why.kind()),
    65. Ok(paths) => for path in paths {
    66. println!("> {:?}", path.unwrap().path());
    67. },
    68. }
    69. println!("`rm a/c/e.txt`");
    70. // 删除一个文件,返回 `io::Result<()>`
    71. fs::remove_file("a/c/e.txt").unwrap_or_else(|why| {
    72. println!("! {:?}", why.kind());
    73. });
    74. println!("`rmdir a/c/d`");
    75. // 移除一个空目录,返回 `io::Result<()>`
    76. fs::remove_dir("a/c/d").unwrap_or_else(|why| {
    77. println!("! {:?}", why.kind());
    78. });
    79. }

    下面是预期成功的输出:

    1. $ rustc fs.rs && ./fs
    2. `mkdir a`
    3. `echo hello > a/b.txt`
    4. `mkdir -p a/c/d`
    5. `touch a/c/e.txt`
    6. `ln -s ../b.txt a/c/b.txt`
    7. `cat a/c/b.txt`
    8. > hello
    9. `ls a`
    10. > a/b.txt
    11. > a/c
    12. `walk a`
    13. > a/c
    14. > a/c/b.txt
    15. > a/c/e.txt
    16. > a/c/d
    17. > a/b.txt
    18. `rm a/c/e.txt`
    19. `rmdir a/c/d`

    a 目录的最终状态为:

    1. $ tree a
    2. a
    3. |-- b.txt
    4. `-- c
    5. `-- b.txt -> ../b.txt
    6. 1 directory, 2 files

    另一种定义 cat 函数的方式是使用 ? 标记:

    1. fn cat(path: &Path) -> io::Result<String> {
    2. let mut f = File::open(path)?;
    3. let mut s = String::new();
    4. f.read_to_string(&mut s)?;
    5. Ok(s)
    6. }

    参见:

    cfg!