Как я могу прочитать весь файл в строковую переменную

161

У меня много маленьких файлов, я не хочу читать их построчно.

Есть ли в Go функция, которая будет читать весь файл в строковую переменную?

WoooHaaaa
источник

Ответы:

253

Используйте ioutil.ReadFile:

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

ReadFile читает файл с именем filename и возвращает его содержимое. Успешный вызов возвращает err == nil, а не err == EOF. Поскольку ReadFile читает весь файл, он не рассматривает EOF из Read как ошибку, о которой будет сообщено.

Вы получите []byteвместо string. Это может быть преобразовано, если действительно необходимо:

s := string(buf)
ZZZZ
источник
5
Затем для построения конечного результата строки вы можете использовать append () для накопления данных в одном байтовом фрагменте при чтении каждого файла, а затем преобразовать накопленный байтовый фрагмент в конечный результат строки. В качестве альтернативы вам могут понравиться байты.
Соня
1
Покажите нам, как преобразовать его тогда ... Вопрос не задает байтовый массив.
Кайл Бриденстайн
Используя это, чтобы открыть html-файл, и я обнаружил, что после каждой строки добавляется новая строка, которая мешает нам в части моего форматирования. Есть ли способ избежать этого?
Джонатан
55

Если вы просто хотите контент как string, тогда простое решение - использовать ReadFileфункцию из io/ioutilпакета. Эта функция возвращает фрагмент, bytesкоторый вы можете легко преобразовать в 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
источник
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 перезапишет содержимое буфера? А какова вместимость буф? Спасибо.
WoooHaaaa
Копирование не будет перезаписывать, оно будет просто добавляться в buf, и buf будет расти столько, сколько нужно для размещения новых данных.
Бегущий Дикий
1
Буф имеет «бесконечную» емкость. Он будет продолжать расширяться по мере добавления новых данных. ioutil.Readfile выделит буфер, который достаточно большой, чтобы вместить весь файл и не нужно перераспределять.
Стивен Вайнберг
1
Действительно ли использование байтового буфера повышает производительность по сравнению с простым добавлением его в срез (/ массив)? Как насчет памяти? Насколько велика разница?
Киссаки
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()
}
fwhez
источник