mirror of https://github.com/sunface/rust-course
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
151 lines
4.1 KiB
151 lines
4.1 KiB
3 years ago
|
## 读取全部内容
|
||
|
|
||
|
```rust
|
||
|
use std::fs::File;
|
||
|
use std::io::prelude::*;
|
||
|
use std::path::Path;
|
||
|
|
||
|
fn main() {
|
||
|
// Create a path to the desired file
|
||
|
let path = Path::new("hello.txt");
|
||
|
let display = path.display();
|
||
|
|
||
|
// Open the path in read-only mode, returns `io::Result<File>`
|
||
|
let mut file = match File::open(&path) {
|
||
|
Err(why) => panic!("couldn't open {}: {}", display, why),
|
||
|
Ok(file) => file,
|
||
|
};
|
||
|
|
||
|
// Read the file contents into a string, returns `io::Result<usize>`
|
||
|
let mut s = String::new();
|
||
|
match file.read_to_string(&mut s) {
|
||
|
Err(why) => panic!("couldn't read {}: {}", display, why),
|
||
|
Ok(_) => print!("{} contains:\n{}", display, s),
|
||
|
}
|
||
|
|
||
|
// `file` goes out of scope, and the "hello.txt" file gets closed
|
||
|
}
|
||
|
```
|
||
|
|
||
|
## 读取全部行
|
||
|
This process is more efficient than creating a String in memory especially working with larger files.
|
||
|
|
||
|
```rust
|
||
|
use std::fs::File;
|
||
|
use std::io::{self, BufRead};
|
||
|
use std::path::Path;
|
||
|
|
||
|
fn main() {
|
||
|
// File hosts must exist in current path before this produces output
|
||
|
if let Ok(lines) = read_lines("./hosts") {
|
||
|
// Consumes the iterator, returns an (Optional) String
|
||
|
for line in lines {
|
||
|
if let Ok(ip) = line {
|
||
|
println!("{}", ip);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// The output is wrapped in a Result to allow matching on errors
|
||
|
// Returns an Iterator to the Reader of the lines of the file.
|
||
|
fn read_lines<P>(filename: P) -> io::Result<io::Lines<io::BufReader<File>>>
|
||
|
where P: AsRef<Path>, {
|
||
|
let file = File::open(filename)?;
|
||
|
Ok(io::BufReader::new(file).lines())
|
||
|
}
|
||
|
```
|
||
|
|
||
|
## 一些常用的文件操作
|
||
|
```rust
|
||
|
use std::fs;
|
||
|
use std::fs::{File, OpenOptions};
|
||
|
use std::io;
|
||
|
use std::io::prelude::*;
|
||
|
use std::os::unix;
|
||
|
use std::path::Path;
|
||
|
|
||
|
fn cat(path: &Path) -> io::Result<String> {
|
||
|
let mut f = File::open(path)?;
|
||
|
let mut s = String::new();
|
||
|
f.read_to_string(&mut s)?;
|
||
|
Ok(s)
|
||
|
}
|
||
|
|
||
|
// A simple implementation of `% echo s > path`
|
||
|
fn echo(s: &str, path: &Path) -> io::Result<()> {
|
||
|
let mut f = File::create(path)?;
|
||
|
|
||
|
f.write_all(s.as_bytes())
|
||
|
}
|
||
|
|
||
|
// A simple implementation of `% touch path` (ignores existing files)
|
||
|
fn touch(path: &Path) -> io::Result<()> {
|
||
|
match OpenOptions::new().create(true).write(true).open(path) {
|
||
|
Ok(_) => Ok(()),
|
||
|
Err(e) => Err(e),
|
||
|
}
|
||
|
}
|
||
|
|
||
|
fn main() {
|
||
|
println!("`mkdir a`");
|
||
|
// Create a directory, returns `io::Result<()>`
|
||
|
match fs::create_dir("a") {
|
||
|
Err(why) => println!("! {:?}", why.kind()),
|
||
|
Ok(_) => {},
|
||
|
}
|
||
|
|
||
|
println!("`echo hello > a/b.txt`");
|
||
|
// The previous match can be simplified using the `unwrap_or_else` method
|
||
|
echo("hello", &Path::new("a/b.txt")).unwrap_or_else(|why| {
|
||
|
println!("! {:?}", why.kind());
|
||
|
});
|
||
|
|
||
|
println!("`mkdir -p a/c/d`");
|
||
|
// Recursively create a directory, returns `io::Result<()>`
|
||
|
fs::create_dir_all("a/c/d").unwrap_or_else(|why| {
|
||
|
println!("! {:?}", why.kind());
|
||
|
});
|
||
|
|
||
|
println!("`touch a/c/e.txt`");
|
||
|
touch(&Path::new("a/c/e.txt")).unwrap_or_else(|why| {
|
||
|
println!("! {:?}", why.kind());
|
||
|
});
|
||
|
|
||
|
println!("`ln -s ../b.txt a/c/b.txt`");
|
||
|
// Create a symbolic link, returns `io::Result<()>`
|
||
|
if cfg!(target_family = "unix") {
|
||
|
unix::fs::symlink("../b.txt", "a/c/b.txt").unwrap_or_else(|why| {
|
||
|
println!("! {:?}", why.kind());
|
||
|
});
|
||
|
}
|
||
|
|
||
|
println!("`cat a/c/b.txt`");
|
||
|
match cat(&Path::new("a/c/b.txt")) {
|
||
|
Err(why) => println!("! {:?}", why.kind()),
|
||
|
Ok(s) => println!("> {}", s),
|
||
|
}
|
||
|
|
||
|
println!("`ls a`");
|
||
|
// Read the contents of a directory, returns `io::Result<Vec<Path>>`
|
||
|
match fs::read_dir("a") {
|
||
|
Err(why) => println!("! {:?}", why.kind()),
|
||
|
Ok(paths) => for path in paths {
|
||
|
println!("> {:?}", path.unwrap().path());
|
||
|
},
|
||
|
}
|
||
|
|
||
|
println!("`rm a/c/e.txt`");
|
||
|
// Remove a file, returns `io::Result<()>`
|
||
|
fs::remove_file("a/c/e.txt").unwrap_or_else(|why| {
|
||
|
println!("! {:?}", why.kind());
|
||
|
});
|
||
|
|
||
|
println!("`rmdir a/c/d`");
|
||
|
// Remove an empty directory, returns `io::Result<()>`
|
||
|
fs::remove_dir("a/c/d").unwrap_or_else(|why| {
|
||
|
println!("! {:?}", why.kind());
|
||
|
}
|
||
|
}
|
||
|
```
|