4

I'm trying to read in a list of numbers from a file (where each line has a number on it) into a Vec<i64> with Rust. I can get the numbers loaded from the file as strings using a BufReader. However, I can't seem to get the value of the strings out of the Result enum they are wrapped in by the BufReader.

So how does one get those values out of Result to parse, so they can populate a Vec with another type than strings?

What I have tried:

  1. Using a for loop where I can print the values to prove they're there, but it panics on the parse when I try to compile with the numbers.append(...) line.
fn load_from_file(file_path: &str) {
    let file = File::open(file_path).expect("file wasn't found.");
    let reader = BufReader::new(file);
    let numbers: Vec<i64> = Vec::new();

    for line in reader.lines() {
        // prints just fine
        println!("line: {:?}", line);
        numbers.append(line.unwrap().parse::<i64>());
    }
}
  1. Alternatively I tried mapping instead, but I encounter the same issue with getting the values into the Vec<i64> I'm trying to populate.
fn load_from_file(file_path: &str) {
    let file = File::open(file_path).expect("file wasn't found.");
    let reader = BufReader::new(file);

    let numbers: Vec<i64> = reader
        .lines()
        .map(|line| line.unwrap().parse::<i64>().collect());
}

This is not solved solely by How to do error handling in Rust and what are the common pitfalls?

pretzelhammer
  • 13,874
  • 15
  • 47
  • 98
CoderLee
  • 3,079
  • 3
  • 25
  • 57
  • 1
    Does this answer your question? [How to do error handling in Rust and what are the common pitfalls?](https://stackoverflow.com/questions/30505639/how-to-do-error-handling-in-rust-and-what-are-the-common-pitfalls) – kmdreko Dec 02 '20 at 00:25
  • That's an informative question but doesn't help solve my problem or discuss Result, BufReader, etc – CoderLee Dec 02 '20 at 15:18
  • It goes over error handling in general, which primarily uses `Result`s. It goes over `.unwrap()`, the `?` operator for propagating errors (a shorthand for an `Ok`/`Err` match), and other transformative functions. You're right that it doesn't answer you directly, but I hope it gives you the tools necessary for handling errors in the future. `.unwrap()` is a blunt tool and not always the best choice. – kmdreko Dec 02 '20 at 19:48
  • 1
    @kmdreko Thank you for the explanation, that is a very helpful question/answer. For those newer to Rust it's difficult to pull out of that info what's needed to solve this kind of problem. That's why I think both questions are valuable, and not quite close enough to be a *duplicate* or *answered elsewhere*. I do see how closely related they are they are though. – CoderLee Dec 03 '20 at 02:11

1 Answers1

6

You can call the unwrap() method on Result enums to get values out of them. Fixed example:

use std::fs::File;
use std::io::BufReader;
use std::io::BufRead;

fn load_from_file(file_path: &str) {
    let file = File::open(file_path).expect("file wasn't found.");
    let reader = BufReader::new(file);

    let numbers: Vec<i64> = reader
        .lines()
        .map(|line| line.unwrap().parse::<i64>().unwrap())
        .collect();
}

playground

pretzelhammer
  • 13,874
  • 15
  • 47
  • 98
  • So you have to unwrap the *line* to parse it, then unwrap again inside the map to then collect the values? Would mind explaining a little more on why you unwrap twice? Thanks – CoderLee Dec 02 '20 at 00:34
  • 4
    @CoderLee `.lines()` works over any buffered reader meaning individual lines can fail for IO reasons. Parsing the string into an i64 can also fail. Since they are both fallible, they both return `Result`s that must be handled (via `.unwrap()` in this case) – kmdreko Dec 02 '20 at 00:41