skrrskrr
skrrskrr

Reputation: 65

How to read a text File in Rust and read mutliple Values per line

So basically, I have a text file with the following syntax:

String int    
String int  
String int

I have an idea how to read the Values if there is only one entry per line, but if there are multiple, I do not know how to do it.

In Java, I would do something simple with while and Scanner but in Rust I have no clue.

I am fairly new to Rust so please help me.

Thanks for your help in advance

Solution
Here is my modified Solution of @netwave 's code:

use std::fs;
use std::io::{BufRead, BufReader, Error};

fn main() -> Result<(), Error> {
    let buff_reader = BufReader::new(fs::File::open(file)?);
    for line in buff_reader.lines() {
        let parsed = sscanf::scanf!(line?, "{} {}", String, i32);
        println!("{:?}\n", parsed);
    }
    Ok(())
}

Upvotes: 2

Views: 3227

Answers (2)

Netwave
Netwave

Reputation: 42786

You can use the BuffRead trait, which has a read_line method. Also you can use lines.

For doing so the easiest option would be to wrap the File instance with a BuffReader:

use std::fs;
use std::io::{BufRead, BufReader};
...
let buff_reader = BufReader::new(fs::File::open(path)?);
loop {
    let mut buff = String::new();
    buff_reader.read_line(&mut buff)?;
    println!("{}", buff);
}

Playground

Once you have each line you can easily use sscanf crate to parse the line to the types you need:

let parsed = sscanf::scanf!(buff, "{} {}", String, i32);

Upvotes: 3

bits
bits

Reputation: 1705

Based on: https://doc.rust-lang.org/rust-by-example/std_misc/file/read_lines.html

For data.txt to contain:

str1 100
str2 200
str3 300
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("./data.txt") {
        // Consumes the iterator, returns an (Optional) String
        for line in lines {
            if let Ok(data) = line {
                let values: Vec<&str> = data.split(' ').collect();
                match values.len() {
                  2 => {
                    let strdata = values[0].parse::<String>();
                    let intdata =  values[1].parse::<i32>();
                    println!("Got: {:?} {:?}", strdata, intdata);
                  },
                  _ => panic!("Invalid input line {}", data),
                };
            }
        }
    }
}

// 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())
}

Outputs:

Got: Ok("str1") Ok(100)
Got: Ok("str2") Ok(200)
Got: Ok("str3") Ok(300)

Upvotes: 0

Related Questions