Answers:
注意:可接受的答案在早期的Go版本中是正确的。 请参阅投票率最高的答案,其中包含更新的惯用方式。
包中有ReadLine函数bufio。
请注意,如果该行不适合读取缓冲区,则该函数将返回不完整的行。如果要始终通过单次调用函数来读取程序中的整行,则需要将该ReadLine函数封装到自己的函数中,该函数ReadLine在for循环中进行调用。
bufio.ReadString('\n')之所以不完全等效,ReadLine是因为ReadString无法处理文件的最后一行不以换行符结尾的情况。
在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)
    for scanner.Scan() {
        fmt.Println(scanner.Text())
    }
    if err := scanner.Err(); err != nil {
        log.Fatal(err)
    }
}这是Reader逐行读取的最干净的方法。
有一个警告:扫描程序不能处理超过65536个字符的行。如果这对您来说是个问题,那么您可能应该在上滚动Reader.Read()。
file, _ := os.Open("/path/to/file.csv")扫描然后再扫描文件句柄将是微不足道的:scanner := bufio.NewScanner(file)
                    defer file.Close()。
                    bufio.ErrTooLong错误消息,即bufio.Scanner: token too long行太长。在这种情况下,您将必须使用bufio.ReaderLine()或ReadString()。
                    采用:
reader.ReadString('\n')
\n在返回字符串的末尾。reader.ReadLine()
我编写了一个程序来测试在其他答案中被认为是问题的方案,从而测试了各种解决方案:
我找到:
Scanner解决方案无法处理长行。ReadLine解决方案实施起来很复杂。ReadString解决方案是最简单的,适用于排长队。这是演示每种解决方案的代码,可以通过go run main.go以下方式运行:
package main
import (
    "bufio"
    "bytes"
    "fmt"
    "io"
    "os"
)
func readFileWithReadString(fn string) (err error) {
    fmt.Println("readFileWithReadString")
    file, err := os.Open(fn)
    defer file.Close()
    if err != nil {
        return err
    }
    // Start reading from the file with a reader.
    reader := bufio.NewReader(file)
    var line string
    for {
        line, err = reader.ReadString('\n')
        fmt.Printf(" > Read %d characters\n", len(line))
        // Process the line here.
        fmt.Println(" > > " + limitLength(line, 50))
        if err != nil {
            break
        }
    }
    if err != io.EOF {
        fmt.Printf(" > Failed!: %v\n", err)
    }
    return
}
func readFileWithScanner(fn string) (err error) {
    fmt.Println("readFileWithScanner - this will fail!")
    // Don't use this, it doesn't work with long lines...
    file, err := os.Open(fn)
    defer file.Close()
    if err != nil {
        return err
    }
    // Start reading from the file using a scanner.
    scanner := bufio.NewScanner(file)
    for scanner.Scan() {
        line := scanner.Text()
        fmt.Printf(" > Read %d characters\n", len(line))
        // Process the line here.
        fmt.Println(" > > " + limitLength(line, 50))
    }
    if scanner.Err() != nil {
        fmt.Printf(" > Failed!: %v\n", scanner.Err())
    }
    return
}
func readFileWithReadLine(fn string) (err error) {
    fmt.Println("readFileWithReadLine")
    file, err := os.Open(fn)
    defer file.Close()
    if err != nil {
        return err
    }
    // Start reading from the file with a reader.
    reader := bufio.NewReader(file)
    for {
        var buffer bytes.Buffer
        var l []byte
        var isPrefix bool
        for {
            l, isPrefix, err = reader.ReadLine()
            buffer.Write(l)
            // If we've reached the end of the line, stop reading.
            if !isPrefix {
                break
            }
            // If we're just at the EOF, break
            if err != nil {
                break
            }
        }
        if err == io.EOF {
            break
        }
        line := buffer.String()
        fmt.Printf(" > Read %d characters\n", len(line))
        // Process the line here.
        fmt.Println(" > > " + limitLength(line, 50))
    }
    if err != io.EOF {
        fmt.Printf(" > Failed!: %v\n", err)
    }
    return
}
func main() {
    testLongLines()
    testLinesThatDoNotFinishWithALinebreak()
}
func testLongLines() {
    fmt.Println("Long lines")
    fmt.Println()
    createFileWithLongLine("longline.txt")
    readFileWithReadString("longline.txt")
    fmt.Println()
    readFileWithScanner("longline.txt")
    fmt.Println()
    readFileWithReadLine("longline.txt")
    fmt.Println()
}
func testLinesThatDoNotFinishWithALinebreak() {
    fmt.Println("No linebreak")
    fmt.Println()
    createFileThatDoesNotEndWithALineBreak("nolinebreak.txt")
    readFileWithReadString("nolinebreak.txt")
    fmt.Println()
    readFileWithScanner("nolinebreak.txt")
    fmt.Println()
    readFileWithReadLine("nolinebreak.txt")
    fmt.Println()
}
func createFileThatDoesNotEndWithALineBreak(fn string) (err error) {
    file, err := os.Create(fn)
    defer file.Close()
    if err != nil {
        return err
    }
    w := bufio.NewWriter(file)
    w.WriteString("Does not end with linebreak.")
    w.Flush()
    return
}
func createFileWithLongLine(fn string) (err error) {
    file, err := os.Create(fn)
    defer file.Close()
    if err != nil {
        return err
    }
    w := bufio.NewWriter(file)
    fs := 1024 * 1024 * 4 // 4MB
    // Create a 4MB long line consisting of the letter a.
    for i := 0; i < fs; i++ {
        w.WriteRune('a')
    }
    // Terminate the line with a break.
    w.WriteRune('\n')
    // Put in a second line, which doesn't have a linebreak.
    w.WriteString("Second line.")
    w.Flush()
    return
}
func limitLength(s string, length int) string {
    if len(s) < length {
        return s
    }
    return s[:length]
}我测试了:
测试程序输出:
Long lines
readFileWithReadString
 > Read 4194305 characters
 > > aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
 > Read 12 characters
 > > Second line.
readFileWithScanner - this will fail!
 > Failed!: bufio.Scanner: token too long
readFileWithReadLine
 > Read 4194304 characters
 > > aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
 > Read 12 characters
 > > Second line.
No linebreak
readFileWithReadString
 > Read 28 characters
 > > Does not end with linebreak.
readFileWithScanner - this will fail!
 > Read 28 characters
 > > Does not end with linebreak.
readFileWithReadLine
 > Read 28 characters
 > > Does not end with linebreak.defer file.Close()应该是错误检查后; 否则会出错。
                    我写了一种方法,可以轻松地从文件中读取每一行。Readln(* bufio.Reader)函数从基础bufio.Reader结构返回一行(sans \ n)。
// Readln returns a single line (without the ending \n)
// from the input buffered reader.
// An error is returned iff there is an error with the
// buffered reader.
func Readln(r *bufio.Reader) (string, error) {
  var (isPrefix bool = true
       err error = nil
       line, ln []byte
      )
  for isPrefix && err == nil {
      line, isPrefix, err = r.ReadLine()
      ln = append(ln, line...)
  }
  return string(ln),err
}您可以使用Readln读取文件中的每一行。以下代码读取文件中的每一行,并将每一行输出到stdout。
f, err := os.Open(fi)
if err != nil {
    fmt.Printf("error opening file: %v\n",err)
    os.Exit(1)
}
r := bufio.NewReader(f)
s, e := Readln(r)
for e == nil {
    fmt.Println(s)
    s,e = Readln(r)
}干杯!
有两种常见的方式逐行读取文件。
在我的测试用例中,〜250MB,〜2,500,000 行,bufio.Scanner(使用时间:0.395491384s)比bufio.Reader.ReadString(使用时间:0.446867622s)更快。
源代码: https //github.com/xpzouying/go-practice/tree/master/read_file_line_by_line
使用bufio.Scanner读取文件,
func scanFile() {
    f, err := os.OpenFile(logfile, os.O_RDONLY, os.ModePerm)
    if err != nil {
        log.Fatalf("open file error: %v", err)
        return
    }
    defer f.Close()
    sc := bufio.NewScanner(f)
    for sc.Scan() {
        _ = sc.Text()  // GET the line string
    }
    if err := sc.Err(); err != nil {
        log.Fatalf("scan file error: %v", err)
        return
    }
}使用bufio.Reader读取文件,
func readFileLines() {
    f, err := os.OpenFile(logfile, os.O_RDONLY, os.ModePerm)
    if err != nil {
        log.Fatalf("open file error: %v", err)
        return
    }
    defer f.Close()
    rd := bufio.NewReader(f)
    for {
        line, err := rd.ReadString('\n')
        if err != nil {
            if err == io.EOF {
                break
            }
            log.Fatalf("read file line error: %v", err)
            return
        }
        _ = line  // GET the line string
    }
}bufio.Reader示例不以换行符结尾,则不会读取文件的最后一行。ReadString将同时返回最后一行io.EOF。
                    这个要点的例子
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)create并使用ch, err := reader.ReadByte()或concat我自己的缓冲区len, err := reader.Read(myBuffer)
我使用的另一种方式(用上面的文件替换os.Stdin),当行很长(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
}-1?
                    您还可以使用带有\ 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
    }
  }bufio.Reader.ReadLine()运作良好。但是,如果要按字符串读取每一行,请尝试使用ReadString('\ n')。不需要重新发明轮子。
// strip '\n' or read until EOF, return error if read error  
func readline(reader io.Reader) (line []byte, err error) {   
    line = make([]byte, 0, 100)                              
    for {                                                    
        b := make([]byte, 1)                                 
        n, er := reader.Read(b)                              
        if n > 0 {                                           
            c := b[0]                                        
            if c == '\n' { // end of line                    
                break                                        
            }                                                
            line = append(line, c)                           
        }                                                    
        if er != nil {                                       
            err = er                                         
            return                                           
        }                                                    
    }                                                        
    return                                                   
}                                    我喜欢Lzap解决方案,我是Go的新手,我想问一下lzap,但我还不能做到,我还没有50分。
package main
import (
    "bufio"
    "fmt"
    "io"
    "os"
)
func main() {
    f, err := os.Open("archiveName")
    if err != nil {
        fmt.Println(err)
        os.Exit(1)
    }
    defer f.Close()
    r := bufio.NewReader(f)
    line, err := r.ReadString(10)    // line defined once 
    for err != io.EOF {
        fmt.Print(line)              // or any stuff
        line, err = r.ReadString(10) //  line was defined before
    }
}我不确定为什么我需要再次测试'err',但是无论如何我们都能做到。但是,主要问题是..为什么Go在循环内不会在句子=>行err:= r.ReadString(10)上产生错误?每次循环执行一次又一次定义。我可以通过更改来避免这种情况,对此有何评论?我也在'for'中将条件EOF设置为类似于While。谢谢
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),但它需要有空格的所有字符串,如:“我的名字是......”
var name string = ReadFromStdin()
println(name)