EOF后如何再次从标准输入中读取?

约瑟夫·西布尔-恢复莫妮卡

我有以下C程序:

#include <stdio.h>
#include <unistd.h>

void readAndEchoAll(void) {
    for(;;) {
        char buf[100];
        ssize_t size = read(STDIN_FILENO, buf, sizeof(buf));
        if(size <= 0) {
            return;
        }
        fwrite(buf, 1, size, stdout);
    }
}

int main(void) {
    puts("Reading and echoing STDIN until first EOF...");
    readAndEchoAll();
    puts("Got first EOF. Now reading and echoing STDIN until second EOF...");
    readAndEchoAll();
    puts("Got second EOF.");
    return 0;
}

当我运行它时,它会按照我想要的方式工作。这是它的作用:

Reading and echoing STDIN until first EOF...
asdf
^Dasdf
Got first EOF. Now reading and echoing STDIN until second EOF...
fdsa
^Dfdsa
Got second EOF.

我正在尝试创建一个等效的Haskell程序。这是我的尝试:

readAndEchoAll :: IO ()
readAndEchoAll = do
    buf <- getContents
    putStr buf

main :: IO ()
main = do
    putStrLn "Reading and echoing STDIN until first EOF..."
    readAndEchoAll
    putStrLn "Got first EOF. Now reading and echoing STDIN until second EOF..."
    -- ???
    readAndEchoAll
    putStrLn "Got second EOF."

这行不通。这是它的作用:

Reading and echoing STDIN until first EOF...
asdf
^Dasdf
Got first EOF. Now reading and echoing STDIN until second EOF...
readtwice.hs: <stdin>: hGetContents: illegal operation (handle is closed)

如何使这项工作像C程序一样?我假设我需要把clearerr(stdin);我所拥有位置与之等效-- ???,但是我不确定那是什么。

更新:事实证明clearerr它有点麻烦,因为它是标准C API所独有的。使用POSIX API时,您无需做任何等同的工作即可再次阅读。因此,除了让Haskell进行任何其他操作外,我还需要使其不做任何事情:一旦看到EOF,就不要阻止进一步的读取。

丹尼尔·瓦格纳

您不能使用getContents,因为hGetContents(半)关闭了它传递的句柄并getContents调用hGetContents但是在EOF之后使用标准库中的大多数其他功能再次从句柄读取没有问题。这是不使用读取所有字符的简单但效率低下的示例getContents

import Control.Exception
import System.IO.Error

readAll = go [] where
    handler cs err = if isEOFError err
        then return (reverse cs)
        else throwIO err
    go cs = catch (do
        c <- getChar
        go (c:cs))
        (handler cs)

main = do
    all <- readAll
    putStrLn $ "got: " ++ all
    putStrLn "go again, mate"
    all <- readAll
    putStrLn $ "got: " ++ all

如果要提高效率,可以使用各种功能来一次读取行或在标准库中读取其他大块数据,而不是一次读取一个字符。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

从标准输入读取数据时,如何防止“expect”在 EOF 退出?

如何从标准输入中读取进程替换?

如何从标准输入中读取无阻塞?

如何同时从多个输入(文本)文件中读取并进行一些计算后再次打印?

在AngularJS中删除输入值后如何再次验证表单

如何在python中的EOF之前读取用户输入?

如何从标准输入逐行读取?

我该如何从标准输入中读取`read`?

如何从控制台的标准输入中读取?

我如何知道从非阻塞标准输入中读取多少?

如何使此命令从终端上的标准输入中读取密码?

从标准输入中读取时如何处理索引

如何在Groovy脚本中从Bash Heredoc读取标准输入

如何在仍在运行的标准输入中写入进程标准输入并从其标准输出中读取?

在C中从stdin读取某些内容后,如何再次从stdin读取一行?

在python中接受输入和接收输出后如何再次请求输入

在Java中读取输入直到EOF

我该如何读取标准输入?

从Rust中的标准输入读取原始字节

Shell脚本-从标准输入与文件中读取

在Bash管道中读取标准输入

从标准输入中读取任意数量的行

从标准输入中读取地图密钥

在J中读取多行标准输入

golang从标准输入中读取长文本

如何在汇编中逐个字符地从标准输入读取输入

读取c中的输入后如何清除缓冲区?

如何在GNU Prolog中读取用户输入的行,直到命中EOF?

如何从标准输入中读取多行并将其存储在链接列表中