如何增加Go语言中标准输入(Stdin)的最大输入长度?

huangapple go评论96阅读模式
英文:

Go - How increase maximum Stdin input length?

问题

在Go语言中,如果要从标准输入读取超过1024个字符,推荐使用bufio.Reader来替代bufio.Scanner。下面是修改后的代码示例:

package main

import (
	"bufio"
	"fmt"
	"os"
)

func main() {
	reader := bufio.NewReader(os.Stdin)
	input, err := reader.ReadString('\n')
	if err != nil {
		fmt.Println("Error reading input:", err)
		return
	}
	fmt.Println(input)
}

这段代码使用bufio.NewReader创建了一个bufio.Reader对象,然后使用ReadString方法读取输入直到遇到换行符。这样就可以读取超过1024个字符的输入了。

英文:

What's the recommended way to allow more than 1024 characters when reading from standard input in Go?

For example, this code using bufio.Scanner has a maximum input length of 1024.

package main

import (
    "bufio"
    "fmt"
    "os"
)

func main() {
    scanner := bufio.NewScanner(os.Stdin)
    scanner.Scan()
    input := scanner.Text()
    fmt.Println(input)
}

Update after some suggested answers...
Sorry guys - I must still be doing something wrong, or misstated the question. I tried both suggestions and still see the same issue. Below is an updated version of the code. The symptom is that the scanner won't accept input after the 1024th character. e.g. Try to run this then paste in a string that's 1025 characters long, and it'll stop accepting input after character 1024.

package main

import (
    "bufio"
    "bytes"
    "fmt"
    "log"
    "os"
)

func main() {
    var buffer bytes.Buffer
    scanner := bufio.NewScanner(os.Stdin)

    for {
        done := scanner.Scan()
        buffer.WriteString(scanner.Text())
        if done == true {
            if scanner.Err() != nil {
                log.Fatal("Error scanning input")
            }
            break
        }
    }
    fmt.Println(buffer.String())
}

答案1

得分: 5

你正在忽略scanner.Scan()的返回值,它是一个bool类型的值,表示是否已经到达末尾。

具体来说:

当扫描停止时,无论是到达输入的末尾还是出现错误,它都会返回false。在Scan返回false后,Err方法将返回扫描过程中发生的任何错误,但如果是io.EOF,则Err将返回nil。

因此,你需要在一个循环中继续运行scanner.Scan(),直到它返回false,然后检查.Err()以确保扫描停止不是因为非EOF错误。

英文:

You are ignoring the return value of scanner.Scan() which is a bool indicating whether you have reached the end.

Specifically:

> It returns false when the scan stops, either by reaching the end of
> the input or an error. After Scan returns false, the Err method will
> return any error that occurred during scanning, except that if it was
> io.EOF, Err will return nil.

So you need to continue running scanner.Scan() in a loop, until it returns false, then check .Err() to ensure you didn't stop scanning because of a non-EOF error.

答案2

得分: 1

这段代码的主要问题是,如果扫描器(scanner)完成了扫描,scanner.Scan的返回值不是true,而是true表示扫描器还未完成。

在我们修复这个问题的同时,让我们整理一下另一件事情,因为你不需要使用

if done == true

而可以简单地写成

if done

另外,记住done = Scanner.Text(),它作为终止条件,我们可以用下面的代码来整理得更好:

for scanner.Scan() { // 这样做可以实现你想要的效果,循环直到scanner不再为true。
    buffer.WriteString(scanner.Text())
}
if err := scanner.Err(); err != nil {           // 让我们保存err...
    log.Fatalf("扫描输入时出错:%s", err) // 并在这里使用它。
}

你可以舍弃很多行代码,而且只在循环结束时检查一次Err()。不需要使用break。

希望这对你有用,如果你需要其他帮助,请告诉我。

编辑:还有两件事需要注意。

1)bufio.Scanner.Scan()会吃掉所有的分隔符。也许这没关系,或者你想要将它们添加回去。

2)如果你的SplitFunc写错了,或者有人故意输入错误的内容给你的SplitFunc,bufio.Scanner.Scan()可能会引发panic,如果缓冲区变得太大,bytes.Buffer.WriteString()也可能会引发panic。如果你在生产系统中使用它们,请确保以合适的方式处理这些panic。

英文:

The main problem with this code is that the return value of scanner.Scan is not true if the scanner is done, but true if the scanner is not done.

While we're fixing that, let's tidy up another thing, since you don't need to use

if done == true

but can simply do

if done

Also, remember that done = Scanner.Text(), and serves as the terminating condition, and we can tidy up the code really nicely with:

for scanner.Scan() { // This does what you want, looping until scanner
                     // is no longer true.
    buffer.WriteString(scanner.Text())
}
if err := scanner.Err(); err != nil {           // Let's hold on to err...
    log.Fatalf("Error scanning input: %s", err) // and use it here.
}

You get to discard a lot of lines, and you only check Err() once at the end of the loop. No need to use break.

Hope that works for you, and send me a line if you need something else.

Edit: Two more things to be aware of.

  1. bufio.Scanner.Scan() will be eating all your separator tokens. Maybe that's okay, or maybe you want to keep adding them back in.

  2. bufio.Scanner.Scan() may panic if your SplitFunc is wrong, or someone is crafting poor input for your SplitFunc, and bytes.Buffer.WriteString() may panic if the buffer gets too large. If you're using these in a production system, make sure that you handle these panics in whatever way makes sense.

答案3

得分: 0

你可以使用以下代码替代使用Scanner...

reader := bufio.NewReaderSize(os.Stdin, 65536)
line, isPrefix, err := reader.ReadLine()

编写一个辅助函数来持续读取,直到读取完整一行...

func ReadLine(reader *bufio.Reader) (string, error) {
    result := ""
    for {
        line, isPrefix, err := reader.ReadLine()
        if err != nil {
            return result, err
        }
        result += string(line)
        if !isPrefix {
            return result, nil
        }
    }
}
英文:

You can do this instead of using Scanner...

reader := bufio.NewReaderSize(os.Stdin, 65536)
line, isPrefix, err := reader.ReadLine()

Write a helper function to keep reading until you've read a complete line...

func ReadLine(reader *bufio.Reader) (string, error) {
	result := ""
	for {
		line, isPrefix, err := reader.ReadLine()
		if err != nil {
			return result, err
		}
		result += string(line)
		if !isPrefix {
			return result, nil
		}
	}
}

huangapple
  • 本文由 发表于 2015年12月10日 05:33:06
  • 转载请务必保留本文链接:https://go.coder-hub.com/34189401.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定