Wie kann ich eine ganze Datei in eine Stringvariable einlesen?


161

Ich habe viele kleine Dateien, ich möchte sie nicht Zeile für Zeile lesen.

Gibt es in Go eine Funktion, die eine ganze Datei in eine Zeichenfolgenvariable einliest?

Antworten:


253

Verwendung ioutil.ReadFile:

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

ReadFile liest die nach Dateiname benannte Datei und gibt den Inhalt zurück. Ein erfolgreicher Aufruf gibt err == nil zurück, nicht err == EOF. Da ReadFile die gesamte Datei liest, wird ein EOF aus Read nicht als zu meldender Fehler behandelt.

Sie erhalten eine []bytestatt einer string. Es kann umgewandelt werden , wenn wirklich notwendig:

s := string(buf)

5
Um das endgültige Zeichenfolgenergebnis zu erstellen, können Sie mit append () die Daten beim Lesen jeder Datei in einem einzelnen Byte-Slice akkumulieren und dann das akkumulierte Byte-Slice in das endgültige String-Ergebnis konvertieren. Alternativ könnte Ihnen bytes.Join gefallen.
Sonia

1
Zeigen Sie uns, wie man es dann konvertiert ... Die Frage fragt nicht nach einem Byte-Array.
Kyle Bridenstine

Wenn Sie dies verwenden, um eine HTML-Datei zu öffnen, wird nach jeder Zeile eine neue Zeile angehängt, die uns einige meiner Formatierungen durcheinander bringt. Gibt es eine Möglichkeit, dies zu vermeiden?
Jonathan

55

Wenn Sie nur den Inhalt als möchten string, besteht die einfache Lösung darin, die ReadFileFunktion aus dem io/ioutilPaket zu verwenden. Diese Funktion gibt ein Slice zurück, von bytesdem Sie es einfach in ein konvertieren können 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

Ich denke, das Beste, was Sie tun können, wenn Sie wirklich über die Effizienz der Verkettung all dieser Dateien besorgt sind, ist, sie alle in denselben Byte-Puffer zu kopieren.

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

Dies öffnet jede Datei, kopiert ihren Inhalt in buf und schließt die Datei. Abhängig von Ihrer Situation müssen Sie es möglicherweise nicht konvertieren. In der letzten Zeile wird lediglich angezeigt, dass buf.Bytes () die gesuchten Daten enthält.


Hallo, wird io.Copy den Inhalt von buf überschreiben? Und was ist die Kapazität von Buf? Vielen Dank.
WoooHaaaa

Die Kopie wird nicht überschrieben, sondern nur weiter zu buf hinzugefügt, und buf wächst so stark, wie es für die Aufnahme der neuen Daten erforderlich ist.
Laufen wild

1
Der Buf hat eine "unendliche" Kapazität. Es wird weiter erweitert, wenn weitere Daten hinzugefügt werden. ioutil.Readfile weist einen Puffer zu, der groß genug ist, um in die gesamte Datei zu passen, und nicht neu zugewiesen werden muss.
Stephen Weinberg

1
Verbessert die Verwendung eines Bytepuffers wirklich die Leistung im Vergleich zum einfachen Anhängen an das Slice (/ Array)? Was ist mit der Erinnerung? Wie groß ist der Unterschied?
Kissaki

8

So habe ich es gemacht:

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

Ich bin nicht mit Computer, also schreibe ich einen Entwurf. Sie könnten klar sein, was ich sage.

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()
}
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.