Jak mogę wczytać cały plik do zmiennej łańcuchowej


161

Mam dużo małych plików, nie chcę ich czytać linijka po linijce.

Czy w Go jest funkcja, która wczyta cały plik do zmiennej łańcuchowej?

Odpowiedzi:


253

Zastosowanie ioutil.ReadFile:

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

ReadFile czyta plik o nazwie nazwa_pliku i zwraca zawartość. Pomyślne wywołanie zwraca err == nil, a nie err == EOF. Ponieważ ReadFile odczytuje cały plik, nie traktuje EOF z Read jako błędu do zgłoszenia.

Otrzymasz []bytezamiast string. To może być przekształcony czy naprawdę konieczne:

s := string(buf)

5
Następnie, aby skonstruować końcowy wynik w postaci ciągu, możesz użyć metody append (), aby zgromadzić dane w pojedynczym wycinku bajtowym podczas odczytu każdego pliku, a następnie przekonwertować skumulowany segment bajtów na końcowy wynik w postaci ciągu. Alternatywnie możesz polubić bytes.Join.
Sonia

1
Pokaż nam, jak to przekonwertować ... Pytanie nie dotyczy tablicy bajtów.
Kyle Bridenstine,

Używając tego do otwarcia pliku html i stwierdzam, że po każdym wierszu jest dodawany nowy wiersz, który psuje nam część mojego formatowania. Czy jest sposób, aby tego uniknąć?
Jonathan

55

Jeśli chcesz, aby zawartość była po prostu jako string, prostym rozwiązaniem jest użycie ReadFilefunkcji z io/ioutilpakietu. Ta funkcja zwraca wycinek, bytesktóry można łatwo przekonwertować na plik 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

Myślę, że najlepszą rzeczą do zrobienia, jeśli naprawdę martwisz się o skuteczność łączenia wszystkich tych plików, jest skopiowanie ich wszystkich do tego samego bufora bajtów.

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

To otwiera każdy plik, kopiuje jego zawartość do bufora, a następnie zamyka plik. W zależności od sytuacji, w rzeczywistości konwersja może nie być konieczna, ostatnia linia służy po prostu do pokazania, że ​​buf.Bytes () zawiera dane, których szukasz.


Cześć, czy io.Copy nadpisze zawartość bufora? A jaka jest pojemność buforu? Dzięki.
WoooHaaaa

Kopiowanie nie nadpisze, będzie po prostu dodawać do bufora, a wartość buf będzie rosła tak bardzo, jak potrzeba, aby pomieścić nowe dane.
Running Wild

1
Bufor ma „nieskończoną” pojemność. Będzie się nadal rozwijać w miarę dodawania kolejnych danych. ioutil.Readfile przydzieli bufor, który jest wystarczająco duży, aby zmieścić cały plik i nie trzeba go ponownie przydzielać.
Stephen Weinberg

1
Czy użycie bufora bajtów naprawdę poprawia wydajność w porównaniu do prostego dodawania go do plasterka (/ tablicy)? A co z pamięcią? Jak duża jest różnica?
Kissaki

8

Oto jak to zrobiłem:

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

Nie mam komputera, więc piszę szkic. Możesz być pewien, co mówię.

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()
}
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.