ฉันจะอ่านไฟล์ทั้งหมดลงในตัวแปรสตริงได้อย่างไร


161

ฉันมีไฟล์เล็ก ๆ มากมายฉันไม่ต้องการอ่านมันทีละบรรทัด

มีฟังก์ชั่นใน Go ที่จะอ่านไฟล์ทั้งหมดเป็นตัวแปรสตริงหรือไม่?

คำตอบ:


253

การใช้ioutil.ReadFile:

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

ReadFile อ่านไฟล์ที่ชื่อโดยชื่อไฟล์และส่งคืนเนื้อหา การโทรสำเร็จจะส่งคืน err == nil ไม่ใช่ err == EOF เนื่องจาก ReadFile อ่านไฟล์ทั้งหมดจึงไม่ถือว่า EOF จาก Read เป็นข้อผิดพลาดที่ต้องรายงาน

คุณจะได้รับแทน[]byte stringสามารถแปลงหากจำเป็นจริงๆ :

s := string(buf)

5
จากนั้นสำหรับการสร้างผลลัพธ์สตริงสุดท้ายคุณสามารถใช้ผนวก () เพื่อสะสมข้อมูลในชิ้นเดียวไบต์ในขณะที่คุณอ่านแต่ละไฟล์จากนั้นแปลงชิ้นไบต์สะสมเป็นผลสตริงสุดท้าย หรือคุณอาจชอบ bytes.Join
Sonia

1
แสดงวิธีแปลงให้เราดู ... คำถามจะไม่ถามถึงอาร์เรย์ไบต์
Kyle Bridenstine

การใช้สิ่งนี้เพื่อเปิดไฟล์ html และฉันพบว่ามีการขึ้นบรรทัดใหม่ต่อท้ายทุกบรรทัดที่ทำให้การจัดรูปแบบของฉันยุ่งมาก มีวิธีใดที่จะหลีกเลี่ยงปัญหานี้ได้หรือไม่?
Jonathan

55

หากคุณต้องการเนื้อหาเป็นstringวิธีง่าย ๆ คือการใช้ReadFileฟังก์ชั่นจากio/ioutilแพ็คเกจ ฟังก์ชั่นนี้จะส่งกลับชิ้นของที่คุณสามารถแปลงไปเป็นbytesstring

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

การคัดลอกจะไม่เขียนทับมันจะเพิ่มไปยัง buf เสมอและ buf จะเพิ่มขึ้นมากเท่าที่ต้องการเพื่อรองรับข้อมูลใหม่
Wild

1
buf มีความสามารถแบบ "ไม่ จำกัด " มันจะยังคงขยายตัวเมื่อมีการเพิ่มข้อมูลมากขึ้น ioutil.Readfile จะจัดสรรบัฟเฟอร์ที่มีขนาดใหญ่พอที่จะให้พอดีกับไฟล์ที่สมบูรณ์และไม่จำเป็นต้องจัดสรรใหม่
Stephen Weinberg

1
การใช้ bytebuffer ช่วยปรับปรุงประสิทธิภาพจริง ๆ เมื่อเปรียบเทียบกับการต่อท้าย 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()
}
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.