Comment puis-je lire un fichier entier dans une variable de chaîne

161

J'ai beaucoup de petits fichiers, je ne veux pas les lire ligne par ligne.

Existe-t-il une fonction dans Go qui lira un fichier entier dans une variable chaîne?

WoooHaaaa
la source

Réponses:

253

Utilisez ioutil.ReadFile:

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

ReadFile lit le fichier nommé par nom de fichier et renvoie le contenu. Un appel réussi renvoie err == nil, pas err == EOF. Étant donné que ReadFile lit le fichier entier, il ne traite pas un EOF de Read comme une erreur à signaler.

Vous obtiendrez un []byteau lieu d'un string. Il peut être converti si vraiment nécessaire:

s := string(buf)
zzzz
la source
5
Ensuite, pour construire le résultat final de la chaîne, vous pouvez utiliser append () pour accumuler les données dans une tranche d'octet unique lorsque vous lisez chaque fichier, puis convertir la tranche d'octets accumulée en résultat de chaîne final. Sinon, vous pourriez aimer bytes.Join.
Sonia
1
Montrez-nous comment le convertir alors ... La question ne demande pas de tableau d'octets.
Kyle Bridenstine
En l'utilisant pour ouvrir un fichier html, je trouve qu'une nouvelle ligne est ajoutée après chaque ligne, ce qui nous dérange une partie de ma mise en forme. Y a-t-il un moyen d'éviter cela?
Jonathan
55

Si vous voulez simplement que le contenu soit sous forme string, la solution simple consiste à utiliser la ReadFilefonction du io/ioutilpackage. Cette fonction renvoie une tranche debytes dont vous pouvez facilement la convertir en 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
la source
22

Je pense que la meilleure chose à faire, si vous êtes vraiment préoccupé par l'efficacité de la concaténation de tous ces fichiers, est de les copier tous dans le même tampon d'octets.

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

Cela ouvre chaque fichier, copie son contenu dans buf, puis ferme le fichier. Selon votre situation, vous n'aurez peut-être pas besoin de le convertir, la dernière ligne est juste pour montrer que buf.Bytes () a les données que vous recherchez.

Courir sauvage
la source
Bonjour, est-ce que io.Copy écrasera le contenu de buf? Et quelle est la capacité du buf? Merci.
WoooHaaaa
Copy n'écrasera pas, il continuera simplement à s'ajouter à buf, et buf augmentera autant qu'il en a besoin pour accueillir les nouvelles données.
Running Wild
1
Le buf a une capacité "infinie". Il continuera à se développer à mesure que de nouvelles données seront ajoutées. ioutil.Readfile allouera un tampon suffisamment grand pour contenir le fichier complet et qui n'aura pas besoin de réallouer.
Stephen Weinberg
1
L'utilisation d'un bytebuffer améliore-t-elle vraiment les performances par rapport à son simple ajout à la tranche (/ tableau)? Et la mémoire? Quelle est la différence?
Kissaki
8

Voici comment je l'ai fait:

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
la source
-2

Je ne suis pas avec l'ordinateur, alors j'écris un brouillon. Vous pourriez être clair de ce que je dis.

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
la source