我找不到文件。围棋中的ReadLine函数。

如何一行一行地读取文件?


当前回答

在Go 1.1和更新版本中,最简单的方法是使用bufio.Scanner。下面是一个简单的例子,从文件中读取行:

package main

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

func main() {
    file, err := os.Open("/path/to/file.txt")
    if err != nil {
        log.Fatal(err)
    }
    defer file.Close()

    scanner := bufio.NewScanner(file)
    // optionally, resize scanner's capacity for lines over 64K, see next example
    for scanner.Scan() {
        fmt.Println(scanner.Text())
    }

    if err := scanner.Err(); err != nil {
        log.Fatal(err)
    }
}

这是从Reader中逐行读取的最干净的方法。

这里有一个警告:当行长度超过65536个字符时,Scanner将出错。如果你知道你的行长大于64K,使用Buffer()方法来增加扫描仪的容量:

...
scanner := bufio.NewScanner(file)

const maxCapacity int = longLineLen  // your required line length
buf := make([]byte, maxCapacity)
scanner.Buffer(buf, maxCapacity)

for scanner.Scan() {
...

其他回答

注意:在Go的早期版本中,接受的答案是正确的。见投票最高的答案包含了实现这一目标的最新惯用方法。

包bufio中有一个ReadLine函数。

请注意,如果该行不适合读缓冲区,该函数将返回一个不完整的行。如果你想通过对函数的一次调用来读取程序中的整行,你需要将ReadLine函数封装到你自己的函数中,该函数在for循环中调用ReadLine。

bufio.ReadString('\n')并不完全等同于ReadLine,因为ReadString无法处理文件的最后一行不以换行符结束的情况。

这个要点的例子

func readLine(path string) {
  inFile, err := os.Open(path)
  if err != nil {
     fmt.Println(err.Error() + `: ` + path)
     return
  }
  defer inFile.Close()

  scanner := bufio.NewScanner(inFile)
  for scanner.Scan() {
    fmt.Println(scanner.Text()) // the line
  }
}

但是当有一行比扫描器的缓冲区大时,就会出现错误。

当发生这种情况时,我所做的是使用reader:= bufio.NewReader(inFile)创建和concat我自己的缓冲区使用ch, err:= reader. readbyte()或len, err:= reader. read (myBuffer)

我用(替换os)的另一种方法。Stdin with file like above),当行很长(isPrefix)时,它会连接并忽略空行:


func readLines() []string {
  r := bufio.NewReader(os.Stdin)
  bytes := []byte{}
  lines := []string{}
  for {
    line, isPrefix, err := r.ReadLine()
    if err != nil {
      break
    }
    bytes = append(bytes, line...)
    if !isPrefix {
      str := strings.TrimSpace(string(bytes))
      if len(str) > 0 {
        lines = append(lines, str)
        bytes = []byte{}
      }
    }
  }
  if len(bytes) > 0 {
    lines = append(lines, string(bytes))
  }
  return lines
}
import (
     "bufio"
     "os"
)

var (
    reader = bufio.NewReader(os.Stdin)
)

func ReadFromStdin() string{
    result, _ := reader.ReadString('\n')
    witl := result[:len(result)-1]
    return witl
}

下面是一个ReadFromStdin()函数的例子,它类似于fmt.Scan(&name),但它接受所有带空格的字符串,比如:"Hello My Name is…"

var name string = ReadFromStdin()

println(name)

你也可以使用带\n的ReadString作为分隔符:

  f, err := os.Open(filename)
  if err != nil {
    fmt.Println("error opening file ", err)
    os.Exit(1)
  }
  defer f.Close()
  r := bufio.NewReader(f)
  for {
    path, err := r.ReadString(10) // 0x0A separator = newline
    if err == io.EOF {
      // do something here
      break
    } else if err != nil {
      return err // if you return error
    }
  }

在Go 1.16的新版本中,我们可以使用包嵌入来读取文件内容,如下所示。

package main

import _"embed"


func main() {
    //go:embed "hello.txt"
    var s string
    print(s)

    //go:embed "hello.txt"
    var b []byte
    print(string(b))

    //go:embed hello.txt
    var f embed.FS
    data, _ := f.ReadFile("hello.txt")
    print(string(data))
}

欲了解更多详情,请访问https://tip.golang.org/pkg/embed/ 和 https://golangtutorial.dev/tips/embed-files-in-go/