如何将整个文件读入字符串变量


161

我有很多小文件,我不想逐行阅读它们。

Go中是否有将整个文件读入字符串变量的函数?

Answers:


253

用途ioutil.ReadFile

func ReadFile(filename string) ([]byte, error)

ReadFile读取以文件名命名的文件并返回内容。成功的调用将返回err == nil,而不是err == EOF。由于ReadFile读取整个文件,因此不会将Read中的EOF视为要报告的错误。

您会得到一个[]byte而不是string。如果确实需要,可以将其转换为:

s := string(buf)

5
然后,为了构造最终的字符串结果,可以在读取每个文件时使用append()在单个字节片中累积数据,然后将累积的字节片转换为最终的字符串结果。或者,您可能喜欢bytes.Join。
索尼娅2012年

1
向我们展示如何转换它……问题不要求字节数组。
凯尔·布​​莱恩斯汀

使用它来打开一个html文件,我发现每行之后都添加了新行,这使我们有些格式混乱。有什么办法可以避免这种情况?
乔纳森

55

如果只想将内容作为string,则简单的解决方案是使用包中的ReadFile函数io/ioutil。此函数返回一个切片bytes,您可以轻松将其转换为string

package main

import (
    "fmt"
    "io/ioutil"
)

func main() {
    b, err := ioutil.ReadFile("file.txt") // just pass the file name
    if err != nil {
        fmt.Print(err)
    }

    fmt.Println(b) // print the content as 'bytes'

    str := string(b) // convert content to a 'string'

    fmt.Println(str) // print the content as a 'string'
}

22

我认为,如果您真的担心串联所有这些文件的效率,最好的办法是将它们全部复制到同一字节缓冲区中。

buf := bytes.NewBuffer(nil)
for _, filename := range filenames {
  f, _ := os.Open(filename) // Error handling elided for brevity.
  io.Copy(buf, f)           // Error handling elided for brevity.
  f.Close()
}
s := string(buf.Bytes())

这将打开每个文件,将其内容复制到buf中,然后关闭文件。根据您的情况,您可能实际上不需要转换它,最后一行只是显示buf.Bytes()具有您要查找的数据。


嗨,io.Copy会覆盖buf的内容吗?buf的容量是多少?谢谢。
WoooHaaaa 2012年

复制不会覆盖,它只会继续添加到buf中,而buf会根据需要容纳新数据而增长。
野兽

1
该buf具有“无限”的能力。随着添加更多数据,它将继续扩展。ioutil.Readfile将分配一个足以容纳整个文件的缓冲区,而无需重新分配。
史蒂芬·温伯格

1
与仅将字节缓冲区附加到slice(/ array)相比,使用字节缓冲区是否真的提高了性能?那记忆力呢?差异有多大?
Kissaki

8

这是我的方法:

package main

import (
  "fmt"
  "os"
  "bytes"
  "log"
)

func main() {
   filerc, err := os.Open("filename")
   if err != nil{
     log.Fatal(err)
   }
   defer filerc.Close()

   buf := new(bytes.Buffer)
   buf.ReadFrom(filerc)
   contents := buf.String()

   fmt.Print(contents) 

}    

-2

我不在电脑上,所以我写了草稿。您可能不明白我在说什么。

func main(){
    const dir = "/etc/"
    filesInfo, e := ioutil.ReadDir(dir)
    var fileNames = make([]string, 0, 10)
    for i,v:=range filesInfo{
        if !v.IsDir() {
            fileNames = append(fileNames, v.Name())
        }
    }

    var fileNumber = len(fileNames)
    var contents = make([]string, fileNumber, 10)
    wg := sync.WaitGroup{}
    wg.Add(fileNumber)

    for i,_:=range content {
        go func(i int){
            defer wg.Done()
            buf,e := ioutil.Readfile(fmt.Printf("%s/%s", dir, fileName[i]))
            defer file.Close()  
            content[i] = string(buf)
        }(i)   
    }
    wg.Wait()
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.