93 lines
4.0 KiB
HTML
93 lines
4.0 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="en">
|
||
<head>
|
||
<meta charset="UTF-8">
|
||
<title>Reading a File</title>
|
||
</head>
|
||
<body>
|
||
<h2 id="reading-a-file"><a class="header" href="#reading-a-file">Reading a File</a></h2>
|
||
<p>Now we’ll add functionality to read the file specified in the <code>file_path</code>
|
||
argument. First, we need a sample file to test it with: We’ll use a file with a
|
||
small amount of text over multiple lines with some repeated words. Listing 12-3
|
||
has an Emily Dickinson poem that will work well! Create a file called
|
||
<em>poem.txt</em> at the root level of your project, and enter the poem “I’m Nobody!
|
||
Who are you?”</p>
|
||
<figure class="listing" id="listing-12-3">
|
||
<span class="file-name">Filename: poem.txt</span>
|
||
<pre><code class="language-text">I'm nobody! Who are you?
|
||
Are you nobody, too?
|
||
Then there's a pair of us - don't tell!
|
||
They'd banish us, you know.
|
||
|
||
How dreary to be somebody!
|
||
How public, like a frog
|
||
To tell your name the livelong day
|
||
To an admiring bog!
|
||
</code></pre>
|
||
<figcaption><a href="#listing-12-3">Listing 12-3</a>: A poem by Emily Dickinson makes a good test case.</figcaption>
|
||
</figure>
|
||
<p>With the text in place, edit <em>src/main.rs</em> and add code to read the file, as
|
||
shown in Listing 12-4.</p>
|
||
<figure class="listing" id="listing-12-4">
|
||
<span class="file-name">Filename: src/main.rs</span>
|
||
<pre><code class="language-rust should_panic noplayground">use std::env;
|
||
use std::fs;
|
||
|
||
fn main() {
|
||
// --snip--
|
||
<span class="boring"> let args: Vec<String> = env::args().collect();
|
||
</span><span class="boring">
|
||
</span><span class="boring"> let query = &args[1];
|
||
</span><span class="boring"> let file_path = &args[2];
|
||
</span><span class="boring">
|
||
</span><span class="boring"> println!("Searching for {query}");
|
||
</span> println!("In file {file_path}");
|
||
|
||
let contents = fs::read_to_string(file_path)
|
||
.expect("Should have been able to read the file");
|
||
|
||
println!("With text:\n{contents}");
|
||
}</code></pre>
|
||
<figcaption><a href="#listing-12-4">Listing 12-4</a>: Reading the contents of the file specified by the second argument</figcaption>
|
||
</figure>
|
||
<p>First, we bring in a relevant part of the standard library with a <code>use</code>
|
||
statement: We need <code>std::fs</code> to handle files.</p>
|
||
<p>In <code>main</code>, the new statement <code>fs::read_to_string</code> takes the <code>file_path</code>, opens
|
||
that file, and returns a value of type <code>std::io::Result<String></code> that contains
|
||
the file’s contents.</p>
|
||
<p>After that, we again add a temporary <code>println!</code> statement that prints the value
|
||
of <code>contents</code> after the file is read so that we can check that the program is
|
||
working so far.</p>
|
||
<p>Let’s run this code with any string as the first command line argument (because
|
||
we haven’t implemented the searching part yet) and the <em>poem.txt</em> file as the
|
||
second argument:</p>
|
||
<pre><code class="language-console">$ cargo run -- the poem.txt
|
||
Compiling minigrep v0.1.0 (file:///projects/minigrep)
|
||
Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.0s
|
||
Running `target/debug/minigrep the poem.txt`
|
||
Searching for the
|
||
In file poem.txt
|
||
With text:
|
||
I'm nobody! Who are you?
|
||
Are you nobody, too?
|
||
Then there's a pair of us - don't tell!
|
||
They'd banish us, you know.
|
||
|
||
How dreary to be somebody!
|
||
How public, like a frog
|
||
To tell your name the livelong day
|
||
To an admiring bog!
|
||
|
||
</code></pre>
|
||
<p>Great! The code read and then printed the contents of the file. But the code
|
||
has a few flaws. At the moment, the <code>main</code> function has multiple
|
||
responsibilities: Generally, functions are clearer and easier to maintain if
|
||
each function is responsible for only one idea. The other problem is that we’re
|
||
not handling errors as well as we could. The program is still small, so these
|
||
flaws aren’t a big problem, but as the program grows, it will be harder to fix
|
||
them cleanly. It’s a good practice to begin refactoring early on when
|
||
developing a program because it’s much easier to refactor smaller amounts of
|
||
code. We’ll do that next.</p>
|
||
</body>
|
||
</html>
|