Bagaimana saya bisa membaca seluruh file menjadi variabel string

161

Saya punya banyak file kecil, saya tidak ingin membacanya baris demi baris.

Apakah ada fungsi di Go yang akan membaca seluruh file menjadi variabel string?

WoooHaaaa
sumber

Jawaban:

253

Gunakan ioutil.ReadFile:

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

ReadFile membaca file bernama nama file dan mengembalikan konten. Panggilan yang berhasil mengembalikan err == nil, bukan err == EOF. Karena ReadFile membaca seluruh file, itu tidak memperlakukan EOF dari Baca sebagai kesalahan untuk dilaporkan.

Anda akan mendapatkan yang []bytebukan string. Ini dapat dikonversi jika benar - benar diperlukan:

s := string(buf)
zzzz
sumber
5
Kemudian untuk membuat hasil string akhir, Anda dapat menggunakan append () untuk mengakumulasi data dalam satu byte slice saat Anda membaca setiap file, kemudian mengonversi slice byte yang terakumulasi menjadi hasil string akhir. Atau Anda mungkin suka bytes.Gabung.
Sonia
1
Tunjukkan kepada kami cara mengonversi itu lalu ... Pertanyaannya tidak meminta array byte.
Kyle Bridenstine
Menggunakan ini untuk membuka file html dan saya menemukan baris baru ditambahkan setelah setiap baris yang mengacaukan kami beberapa format saya. Apakah ada cara untuk menghindarinya?
Jonathan
55

Jika Anda hanya menginginkan konten sebagai string, maka solusi sederhana adalah dengan menggunakan ReadFilefungsi dari io/ioutilpaket. Fungsi ini mengembalikan sepotong bytesyang Anda dapat dengan mudah dikonversi menjadi 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'
}
openwonk
sumber
22

Saya pikir hal terbaik yang harus dilakukan, jika Anda benar-benar khawatir tentang efisiensi menggabungkan semua file-file ini, adalah menyalin semua ke buffer byte yang sama.

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())

Ini membuka setiap file, menyalin isinya ke buf, lalu menutup file. Bergantung pada situasi Anda, Anda mungkin tidak perlu mengubahnya, baris terakhir hanya untuk menunjukkan bahwa buf.Bytes () memiliki data yang Anda cari.

Berlari liar
sumber
Hai, apakah io.Copy akan menimpa konten buf? Dan berapa kapasitas buf? Terima kasih.
WoooHaaaa
Salin tidak akan menimpa, itu hanya akan terus menambahkan ke buf, dan buf akan tumbuh sebanyak yang dibutuhkan untuk mengakomodasi data baru.
Running Wild
1
Buf memiliki kapasitas "tak terbatas". Ini akan terus berkembang saat lebih banyak data ditambahkan. ioutil.Readfile akan mengalokasikan buffer yang cukup besar agar sesuai dengan file yang lengkap dan tidak perlu realokasi.
Stephen Weinberg
1
Apakah menggunakan bytebuffer benar-benar meningkatkan kinerja dibandingkan dengan hanya menambahkannya ke slice (/ array)? Bagaimana dengan memori? Seberapa besar perbedaannya?
Kissaki
8

Beginilah cara saya melakukannya:

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) 

}    
Mo-Gang
sumber
-2

Saya tidak menggunakan komputer, jadi saya menulis konsep. Anda mungkin jelas dengan apa yang saya katakan.

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()
}
fwhez
sumber