英文:
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个字符,它会悄无声息地失败。你有两个选择。
- 调用
scanner.Buffer()
并提供足够的max
参数。默认情况下,buffer
可能很小,因为Scanner
足够聪明,可以分配新的缓冲区。如果你事先不知道总大小,就像使用原始的Reader
接口一样,并且你有巨大的行 - 内存消耗将随之增长,因为Scanner
记录了所有的行。 - 在外部循环中重新创建
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.
- Call
scanner.Buffer()
and supply the sufficientmax
parameter.buffer
may be small by default becauseScanner
is smart enough to allocate new ones. Can be a problem if you don't know the total size beforehand, like with vanillaReader
interface, and you've got huge lines - the memory consumption will grow correspondingly asScanner
records all the line. - 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("input.txt")
if err != nil {
panic("Error happend during opening the file. Please check if file exists!")
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("%v\n", line)
count++
}
if err := scanner.Err(); err != nil {
fmt.Fprintln(os.Stderr, "reading input:", err)
}
fmt.Printf("%d\n", count)
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论