String 在Go中逐行读取文件
我在Go中找不到String 在Go中逐行读取文件,string,file,parsing,go,line,String,File,Parsing,Go,Line,我在Go中找不到文件.ReadLine函数。我能想出如何快速编写一个,但我只是想知道我是否忽略了一些东西。如何逐行读取文件?注意:在早期版本的Go中,公认的答案是正确的。包含实现此目的的最新惯用方法 包bufio中有函数 请注意,如果该行不适合读取缓冲区,则函数将返回不完整的行。如果您希望通过对函数的一次调用始终读取程序中的整行,则需要将ReadLine函数封装到自己的函数中,该函数在for循环中调用ReadLine bufio.ReadString('\n')并不完全等同于ReadLine,因
文件.ReadLine
函数。我能想出如何快速编写一个,但我只是想知道我是否忽略了一些东西。如何逐行读取文件?注意:在早期版本的Go中,公认的答案是正确的。包含实现此目的的最新惯用方法
包bufio
中有函数
请注意,如果该行不适合读取缓冲区,则函数将返回不完整的行。如果您希望通过对函数的一次调用始终读取程序中的整行,则需要将ReadLine
函数封装到自己的函数中,该函数在for循环中调用ReadLine
bufio.ReadString('\n')
并不完全等同于ReadLine
,因为ReadString
无法处理文件最后一行不以换行符结尾的情况。EDIT:从go1.1开始,惯用的解决方案是使用
我写了一个从文件中轻松读取每一行的方法。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)
}
干杯 效果很好。但是如果你想用一个字符串来读每一行,试着使用。它不需要重新设计控制盘。您也可以将ReadString与\n一起用作分隔符:
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.1及更新版本中,最简单的方法是使用一个。下面是一个从文件中读取行的简单示例:
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)
}
}
这是逐行读取读取器
的最干净的方法
有一个警告:扫描仪不能很好地处理长度超过65536个字符的行。如果这对您来说是一个问题,那么您可能应该在Reader.Read()
这个示例的顶部滚动您自己的
但当有一行比扫描仪的缓冲区大时,就会出现错误
当发生这种情况时,我所做的是使用reader:=bufio.NewReader(infle)
创建并使用ch,err:=reader.ReadByte()
或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
}
在下面的代码中,我从CLI读取兴趣,直到用户点击enter键,我使用的是Readline:
interests := make([]string, 1)
r := bufio.NewReader(os.Stdin)
for true {
fmt.Print("Give me an interest:")
t, _, _ := r.ReadLine()
interests = append(interests, string(t))
if len(t) == 0 {
break;
}
}
fmt.Println(interests)
使用:
reader.ReadString('\n')
- 如果您不介意线路可能很长(即使用大量RAM)。它将
保留在返回的字符串末尾\n
- 如果您不介意线路可能很长(即使用大量RAM)。它将
reader.ReadLine()
- 如果您关心限制RAM消耗,并且不介意处理行大于读取器缓冲区大小的情况的额外工作
- 具有4MB行的文件
- 不以换行符结尾的文件
解决方案不处理长线扫描仪
解决方案实施起来很复杂ReadLine
解决方案是最简单的,适用于长行ReadString
go-run-main.go
,或在
下面是一个函数ReadFromStdin()
的示例,它类似于fmt.Scan(&name)
,但它会使用带有空格的所有字符串,如:“您好,我的名字是…”
有两种常见的方法逐行读取文件
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
}
}
另一种方法是使用
io/ioutil
和strings
库读取整个文件的字节,将它们转换为字符串,并使用“\n
”(换行符)字符作为分隔符拆分它们,例如:
import (
"io/ioutil"
"strings"
)
func main() {
bytesRead, _ := ioutil.ReadFile("something.txt")
file_content := string(bytesRead)
lines := strings.Split(file_content, "\n")
}
从技术上讲,您不是逐行读取文件,但是您可以使用此技术解析每一行。此方法适用于较小的文件。如果您试图解析海量文件,请使用逐行读取的技术。在新版Go 1.16中,我们可以使用package embed读取文件内容,如下所示
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))
}
有关更多详细信息,请浏览
及
在Go 1.1发布之前,我写下了这个答案。Go 1.1在stdlib中有一个扫描仪包。这提供了与我的答案相同的功能。我建议使用Scanner而不是我的答案,因为Scanner在stdlib中。快乐黑客!:-)由于OP要求扫描一个文件,所以先扫描
文件,:=os.Open(“/path/to/file.csv”)
,然后扫描文件句柄:scanner:=bufio.NewScanner(文件)
问题是scanner.scan()限制在每行4096[]字节的缓冲区大小。如果行太长,您将得到bufio.ErrTooLong
error,即bufio.Scanner:token toom long
。在这种情况下,您必须使用bufio.ReaderLine()或ReadString()。仅我的$0.02-这是页面上最正确的答案:)从源代码开始,现在限制为64 KB,而不是4 KB,请参阅:您可以使用其Buffer()方法将扫描仪配置为处理更长的行:从Go1.1开始,bufio.Scanner是最好的方法。从文档:“ReadLine是一种低级的行读取原语。大多数调用者应该使用ReadBytes('\n')或ReadString('\n'),或者使用扫描仪。“@mdwhatcott它为什么会
import (
"bufio"
"os"
)
var (
reader = bufio.NewReader(os.Stdin)
)
func ReadFromStdin() string{
result, _ := reader.ReadString('\n')
witl := result[:len(result)-1]
return witl
}
var name string = ReadFromStdin()
println(name)
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
}
}
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
}
}
import (
"io/ioutil"
"strings"
)
func main() {
bytesRead, _ := ioutil.ReadFile("something.txt")
file_content := string(bytesRead)
lines := strings.Split(file_content, "\n")
}
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))
}