trpl-zh-cn/src/ch12-02-reading-a-file.md

80 lines
3.3 KiB
Markdown
Raw Normal View History

2017-03-05 00:41:41 +08:00
## 读取文件
2018-12-06 21:32:44 +08:00
> [ch12-02-reading-a-file.md](https://github.com/rust-lang/book/blob/master/src/ch12-02-reading-a-file.md)
2017-03-05 00:41:41 +08:00
> <br>
2018-12-06 21:32:44 +08:00
> commit 1fedfc4b96c2017f64ecfcf41a0a07e2e815f24f
2017-03-05 00:41:41 +08:00
2018-12-06 21:32:44 +08:00
现在我们要增加读取由 `filename` 命令行参数指定的文件的功能。首先,需要一个用来测试的示例文件:用来确保 `minigrep` 正常工作的最好的文件是拥有多行少量文本且有一些重复单词的文件。示例 12-3 是一首艾米莉·狄金森Emily Dickinson的诗它正适合这个工作在项目根目录创建一个文件 `poem.txt`,并输入诗 "I'm nobody! Who are you?"
2017-03-05 00:41:41 +08:00
2017-08-28 16:20:19 +08:00
<span class="filename">文件名: poem.txt</span>
2017-03-05 00:41:41 +08:00
2017-04-05 23:13:49 +08:00
```text
2018-12-06 21:32:44 +08:00
I'm nobody! Who are you?
2017-03-05 00:41:41 +08:00
Are you nobody, too?
2018-12-06 21:32:44 +08:00
Then there's a pair of us - don't tell!
They'd banish us, you know.
2017-03-05 00:41:41 +08:00
How dreary to be somebody!
How public, like a frog
To tell your name the livelong day
To an admiring bog!
```
2017-09-27 16:08:38 +08:00
<span class="caption">示例 12-3艾米莉·狄金森的诗 “Im nobody! Who are you?”,一个好的测试用例</span>
2017-03-05 00:41:41 +08:00
2017-09-27 16:08:38 +08:00
创建完这个文件之后,修改 *src/main.rs* 并增加如示例 12-4 所示的打开文件的代码:
2017-03-05 00:41:41 +08:00
2017-08-28 16:20:19 +08:00
<span class="filename">文件名: src/main.rs</span>
2017-03-05 00:41:41 +08:00
2017-04-05 23:13:49 +08:00
```rust,should_panic
2017-03-05 00:41:41 +08:00
use std::env;
2018-12-06 21:32:44 +08:00
use std::fs;
2017-03-05 00:41:41 +08:00
fn main() {
2017-08-28 16:20:19 +08:00
# let args: Vec<String> = env::args().collect();
#
# let query = &args[1];
# let filename = &args[2];
#
# println!("Searching for {}", query);
2018-01-22 10:34:33 +08:00
// --snip--
2017-03-05 00:41:41 +08:00
println!("In file {}", filename);
2018-12-06 21:32:44 +08:00
let contents = fs::read_to_string(filename)
.expect("Something went wrong reading the file");
2017-03-05 00:41:41 +08:00
println!("With text:\n{}", contents);
}
```
2017-09-27 16:08:38 +08:00
<span class="caption">示例 12-4读取第二个参数所指定的文件内容</span>
2017-03-05 00:41:41 +08:00
2018-12-06 21:32:44 +08:00
首先,我们增加了更多的 `use` 语句来引入标准库中的相关部分:需要 `std::fs` 来处理文件。
2017-03-05 00:41:41 +08:00
2018-12-06 21:32:44 +08:00
`main` 中新增了一行语句:`fs::read_to_string` 接受 `filename`,打开文件,接着返回包含其内容的 `Result<String>`
2017-04-05 23:13:49 +08:00
2017-08-28 16:20:19 +08:00
在这些代码之后,我们再次增加了临时的 `println!` 打印出读取文件后 `contents` 的值,这样就可以检查目前为止的程序能否工作。
2017-03-05 00:41:41 +08:00
2017-04-05 23:13:49 +08:00
尝试运行这些代码,随意指定一个字符串作为第一个命令行参数(因为还未实现搜索功能的部分)而将 *poem.txt* 文件将作为第二个参数:
2017-03-05 00:41:41 +08:00
2017-08-28 16:20:19 +08:00
```text
2017-03-05 00:41:41 +08:00
$ cargo run the poem.txt
2018-01-22 10:34:33 +08:00
Compiling minigrep v0.1.0 (file:///projects/minigrep)
2017-08-28 16:20:19 +08:00
Finished dev [unoptimized + debuginfo] target(s) in 0.0 secs
Running `target/debug/minigrep the poem.txt`
2017-03-05 00:41:41 +08:00
Searching for the
In file poem.txt
With text:
2017-08-28 16:20:19 +08:00
Im nobody! Who are you?
2017-03-05 00:41:41 +08:00
Are you nobody, too?
2017-08-28 16:20:19 +08:00
Then theres a pair of us — dont tell!
Theyd banish us, you know.
2017-03-05 00:41:41 +08:00
How dreary to be somebody!
How public, like a frog
To tell your name the livelong day
To an admiring bog!
```
2017-08-28 16:20:19 +08:00
好的!代码读取并打印出了文件的内容。虽然它还有一些瑕疵:`main` 函数有着多个职能,通常函数只负责一个功能的话会更简洁并易于维护。另一个问题是没有尽可能的处理错误。虽然我们的程序还很小,这些瑕疵并不是什么大问题,不过随着程序功能的丰富,将会越来越难以用简单的方法修复他们。在开发程序时,及早开始重构是一个最佳实践,因为重构少量代码时要容易的多,所以让我们现在就开始吧。