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.