Como posso ler um arquivo inteiro em uma variável de string

161

Tenho muitos arquivos pequenos, não quero lê-los linha por linha.

Existe uma função no Go que lê um arquivo inteiro em uma variável de string?

WoooHaaaa
fonte

Respostas:

253

Use ioutil.ReadFile:

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

ReadFile lê o arquivo nomeado pelo nome do arquivo e retorna o conteúdo. Uma chamada bem-sucedida retorna err == nil, não err == EOF. Como o ReadFile lê o arquivo inteiro, ele não trata um EOF de Read como um erro a ser relatado.

Você receberá um em []bytevez de um string. Pode ser convertido se realmente necessário:

s := string(buf)
zzzz
fonte
5
Em seguida, para construir o resultado final da sequência, você pode usar append () para acumular os dados em uma única fatia de bytes à medida que lê cada arquivo e, em seguida, converter a fatia acumulada em bytes no resultado final da sequência. Como alternativa, você pode gostar de bytes.Join.
Sonia
1
Mostre-nos como convertê-lo então ... A pergunta não pede uma matriz de bytes.
Kyle Bridenstine
Usando isso para abrir um arquivo html e acho que uma nova linha é anexada após cada linha que está atrapalhando parte da minha formatação. Existe alguma maneira de evitar isso?
Jonathan
55

Se você deseja apenas o conteúdo como string, a solução simples é usar a ReadFilefunção do io/ioutilpacote. Essa função retorna uma fatia da bytesqual você pode facilmente converter em a 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
fonte
22

Acho que a melhor coisa a fazer, se você estiver realmente preocupado com a eficiência da concatenação de todos esses arquivos, é copiá-los no mesmo buffer de bytes.

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

Isso abre cada arquivo, copia seu conteúdo para o buf e depois fecha o arquivo. Dependendo da sua situação, talvez você não precise convertê-la, a última linha é apenas para mostrar que o buf.Bytes () tem os dados que você está procurando.

Corrida selvagem
fonte
Oi, o io.Copy substituirá o conteúdo do buf? E qual é a capacidade do buf? Obrigado.
WoooHaaaa
A cópia não será substituída, ela continuará adicionando ao buf, e o buf crescerá o quanto for necessário para acomodar os novos dados.
Executando Wild
1
O buf tem uma capacidade "infinita". Ele continuará a se expandir à medida que mais dados forem adicionados. O ioutil.Readfile alocará um buffer grande o suficiente para caber no arquivo completo e não precisará realocar.
Stephen Weinberg
1
O uso de um bytebuffer realmente melhora o desempenho em comparação com simplesmente anexá-lo à fatia (/ array)? E a memória? Quão grande é a diferença?
Kissaki 02/02
8

Foi assim que eu fiz:

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) 

}    
Mo-Gang
fonte
-2

Não estou com computador, então escrevo um rascunho. Você pode ter certeza do que eu digo.

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
fonte