How to avoid buffering on stdin and stdout?

2019-09-02 07:00发布

When reading from std::io::stdin(), input is buffered until EOF is encountered. I'd like to process lines as they arrive, rather than waiting for everything to be buffered.

Given a shell function bar that runs echo bar every second forever, I'm testing this with bar | thingy. It won't print anything until I ^C.

Here's what I'm currently working with:

use std::io;
use std::io::timer;
use std::time::Duration;

fn main() {
    let mut reader = io::stdin();
    let interval = Duration::milliseconds(1000);

    loop {
        match reader.read_line() {
            Ok(l) => print!("{}", l),
            Err(_) => timer::sleep(interval),
        }
    }
}

标签: rust
1条回答
乱世女痞
2楼-- · 2019-09-02 07:24

When reading from std::io::stdin(), input is buffered until EOF is encountered

Why do you say this? Your code appears to work as you want. If I compile it and run it:

$ ./i
hello
hello

goodbye
goodbye

yeah!
yeah!

The first of each pair of lines is me typing into the terminal and hitting enter (which is what read_line looks for). The second is what your program outputs.

Err(_) => timer::sleep(interval)

This is a bad idea - when input is closed (such as by using ^D), your program does not terminate.

Edit

I created a script bar:

#!/bin/bash

set -eu

i=0

while true; do
    echo $i
    sleep 1
done

And then ran it:

./bar | ./i
0

0

0

Your program continues to work.

查看更多
登录 后发表回答