通过bufio计算行数

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

Count lines via bufio

问题

我正在使用bufio来对文本文件中的每一行进行循环。但是我不知道如何计算行数。

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

以上是我用来扫描文件的代码。

英文:

I'm utilizing bufio to do a for loop for each line in a text file. I have no idea how to count the amount of lines though.

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

The above is what I use to scan my file.

答案1

得分: 5

你可以这样做:

counter := 0
for scanner.Scan() {
    line := scanner.Text()
    counter++
    // 处理你的行数据
}
fmt.Printf("读取的行数:%d", counter)
英文:

You could do something like this:

counter := 0
for scanner.Scan() {
    line := scanner.Text()
    counter++
    // do something with your line
}
fmt.Printf("Lines read: %d", counter)

答案2

得分: 1

保持简单和快速。不需要缓冲,scanner已经做了这个。不要进行不必要的string转换。例如,

package main

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

func lineCount(filename string) (int64, error) {
    lc := int64(0)
    f, err := os.Open(filename)
    if err != nil {
        return 0, err
    }
    defer f.Close()
    s := bufio.NewScanner(f)
    for s.Scan() {
        lc++
    }
    return lc, s.Err()
}

func main() {
    filename := `testfile`
    lc, err := lineCount(filename)
    if err != nil {
        fmt.Println(err)
        return
    }
    fmt.Println(filename+" line count:", lc)
}
英文:

Keep it simple and fast. No need for buffering, scanner already does that. Don't do unnecessary string conversions. For example,

package main

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

func lineCount(filename string) (int64, error) {
	lc := int64(0)
	f, err := os.Open(filename)
	if err != nil {
		return 0, err
	}
	defer f.Close()
	s := bufio.NewScanner(f)
	for s.Scan() {
		lc++
	}
	return lc, s.Err()
}

func main() {
	filename := `testfile`
	lc, err := lineCount(filename)
	if err != nil {
		fmt.Println(err)
		return
	}
	fmt.Println(filename+" line count:", lc)
}

答案3

得分: 1

正如我所评论的,被接受的答案在处理长行时会失败。默认限制是bufio.MaxScanTokenSize,它是64KiB。所以如果你的行超过65536个字符,它会悄无声息地失败。你有两个选择。

  1. 调用scanner.Buffer()并提供足够的max参数。默认情况下,buffer可能很小,因为Scanner足够聪明,可以分配新的缓冲区。如果你事先不知道总大小,就像使用原始的Reader接口一样,并且你有巨大的行 - 内存消耗将随之增长,因为Scanner记录了所有的行。
  2. 在外部循环中重新创建scanner,这将确保你继续前进:
var scanner *bufio.Scanner
counter := 0
for scanner == nil || scanner.Err() == bufio.ErrTooLong {
    scanner = bufio.NewScanner(reader)
    for scanner.Scan() {
        counter++
    }
}

(2)的问题是你不断分配和释放缓冲区,而不是重用它们。所以让我们将(1)和(2)合并起来:

var scanner *bufio.Scanner
buffer := make([]byte, bufio.MaxScanTokenSize)
counter := 0
for scanner == nil || scanner.Err() == bufio.ErrTooLong {
    scanner = bufio.NewScanner(reader)
    scanner.Buffer(buffer, 0)
    for scanner.Scan() {
        counter++
    }
}
英文:

As I commented, the accepted answer fails at long lines. The default limit is bufio.MaxScanTokenSize which is 64KiB. So if your line is longer than 65536 chars, it will silently fail. You've got two options.

  1. Call scanner.Buffer() and supply the sufficient max parameter. buffer may be small by default because Scanner is smart enough to allocate new ones. Can be a problem if you don't know the total size beforehand, like with vanilla Reader interface, and you've got huge lines - the memory consumption will grow correspondingly as Scanner records all the line.
  2. Recreate scanner in the outer loop, this will ensure that you advance further:

<!---->

var scanner *bufio.Scanner
counter := 0
for scanner == nil || scanner.Err() == bufio.ErrTooLong {
    scanner = bufio.NewScanner(reader)
    for scanner.Scan() {
        counter++
    }
}

The problem with (2) is that you keep allocating and deallocating buffers instead of reusing them. So let's fuse (1) and (2):

var scanner *bufio.Scanner
buffer := make([]byte, bufio.MaxScanTokenSize)
counter := 0
for scanner == nil || scanner.Err() == bufio.ErrTooLong {
	scanner = bufio.NewScanner(reader)
	scanner.Buffer(buffer, 0)
	for scanner.Scan() {
		counter++
	}
}

答案4

得分: -1

这是我完成任务的方法:

inputFile, err := os.Open("input.txt")

if err != nil {
    panic("打开文件时发生错误,请检查文件是否存在!")
    os.Exit(1)
}

defer inputFile.Close()

inputReader := bufio.NewReader(inputFile)

scanner := bufio.NewScanner(inputReader)
// 统计单词数量。
count := 0
for scanner.Scan() {
    line := scanner.Text()
    fmt.Printf("%v\n", line)
    count++
}
if err := scanner.Err(); err != nil {
    fmt.Fprintln(os.Stderr, "读取输入时出错:", err)
}
fmt.Printf("%d\n", count)

希望这对你有帮助!

英文:

Here is my approach to do the task:

inputFile, err := os.Open(&quot;input.txt&quot;)

if err != nil {
	panic(&quot;Error happend during opening the file. Please check if file exists!&quot;)
	os.Exit(1)
}

defer inputFile.Close()

inputReader := bufio.NewReader(inputFile)

scanner := bufio.NewScanner(inputReader)
// Count the words.
count := 0
for scanner.Scan() {
	line := scanner.Text()
	fmt.Printf(&quot;%v\n&quot;, line)
	count++
}
if err := scanner.Err(); err != nil {
	fmt.Fprintln(os.Stderr, &quot;reading input:&quot;, err)
}
fmt.Printf(&quot;%d\n&quot;, count)

huangapple
  • 本文由 发表于 2015年4月10日 18:39:57
  • 转载请务必保留本文链接:https://go.coder-hub.com/29559358.html
匿名

发表评论

匿名网友

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

确定