如何从标准输入中按字节读取?

How to read bytewise from stdin?

in, out := bufio.NewReader(os.Stdin), bufio.NewWriter(os.Stdout)
for {
    c, err := in.ReadByte()
    if err == io.EOF {
        break
    }
    out.WriteByte(c)
}

我想从标准输入流中按字节读取。不像Read方法ReadByte好像returnio.EOF。如果所有字节都已读取,我该如何中断?

这不是 Reader.ReadByte() implementation, nor that of bufio.NewReader() 的问题。

看这个例子来证明:

buf := bytes.NewBufferString("Hello World!\n")
in := bufio.NewReader(buf)
for {
    c, err := in.ReadByte()
    if err == io.EOF {
        break
    }
    fmt.Print(string(c))
}

当运行时,上面打印

Hello World!

并正确终止。

您的问题与 os.Stdin 有关。从中读取特定于其来源。如果它是你的终端,从它读取只是阻塞而不报告 io.EOF。看这个例子来证明它:

in := bufio.NewReader(os.Stdin)
for {
    fmt.Println("Reading.")
    c, err := in.ReadByte()
    if err == io.EOF {
        break
    }
    fmt.Print(string(c))
}

它的输出是:

Reading.

然后什么也没发生。没有新的迭代,它被阻塞了。现在,如果您输入一行并按 Enter,例如你输入 Go!,输出将是:

Go!
GReading.
oReading.
!Reading.

Reading.

再次等待新的输入。如您所见,每行提供/提供数据。这就是您的终端所做的:当您输入行时,它不会发送到 os.Stdin。一旦您按下 Enter,整行将被送入并可从 os.Stdin 获得。这就是我们看到的:输入的每个字母 Go! 和一个换行符。我们看到每次迭代打印的 Reading. 文本。输入被消耗后,in.ReadByte()再次被阻塞,等待新的输入。它不报告 io.EOF.

现在尝试以下操作:创建一个文件,例如a.txt 并将其编辑为一行:Go! 和一个换行符。现在将此文件作为标准输入提供给您的程序:

go run play.go < a.txt

运行 我们拭目以待:

Reading.
GReading.
oReading.
!Reading.

Reading.

Reading.

它终止所以它有效!它起作用是因为这次 os.Stdin 的来源不是您的控制台/终端,而是文件的内容,一旦它被消耗,尝试从 os.Stdin 读取将正确报告 io.EOF