web-dev-qa-db-fra.com

Lire un fichier texte dans un tableau de chaînes (et écrire)

La capacité de lire (et d'écrire) un fichier texte dans et hors d'un tableau de chaînes est, à mon avis, une exigence assez courante. C'est également très utile lorsque vous démarrez avec une langue, supprimant le besoin initial d'accéder à une base de données. Existe-t-il un à Golang?
par exemple.

func ReadLines(sFileName string, iMinLines int) ([]string, bool) {

et

func WriteLines(saBuff[]string, sFilename string) (bool) { 

Je préférerais utiliser un existant plutôt que de le dupliquer.

93
brianoh

Depuis la version Go1.1, il existe une API bufio.Scanner qui peut facilement lire les lignes d'un fichier. Prenons l'exemple ci-dessus, réécrit avec Scanner:

package main

import (
    "bufio"
    "fmt"
    "log"
    "os"
)

// readLines reads a whole file into memory
// and returns a slice of its lines.
func readLines(path string) ([]string, error) {
    file, err := os.Open(path)
    if err != nil {
        return nil, err
    }
    defer file.Close()

    var lines []string
    scanner := bufio.NewScanner(file)
    for scanner.Scan() {
        lines = append(lines, scanner.Text())
    }
    return lines, scanner.Err()
}

// writeLines writes the lines to the given file.
func writeLines(lines []string, path string) error {
    file, err := os.Create(path)
    if err != nil {
        return err
    }
    defer file.Close()

    w := bufio.NewWriter(file)
    for _, line := range lines {
        fmt.Fprintln(w, line)
    }
    return w.Flush()
}

func main() {
    lines, err := readLines("foo.in.txt")
    if err != nil {
        log.Fatalf("readLines: %s", err)
    }
    for i, line := range lines {
        fmt.Println(i, line)
    }

    if err := writeLines(lines, "foo.out.txt"); err != nil {
        log.Fatalf("writeLines: %s", err)
    }
}
110
Kyle Lemons

Si le fichier n'est pas trop volumineux, vous pouvez le faire avec le ioutil.ReadFile et strings.Split fonctionne comme ceci:

content, err := ioutil.ReadFile(filename)
if err != nil {
    //Do something
}
lines := strings.Split(string(content), "\n")

Vous pouvez lire la documentation sur les paquets ioutil et chaînes .

116
yanatan16

Impossible de mettre à jour la première réponse.
Quoi qu’il en soit, après la sortie de Go1, il y a eu quelques changements radicaux. J'ai donc mis à jour les modifications suivantes:

package main

import (
    "os"
    "bufio"
    "bytes"
    "io"
    "fmt"
    "strings"
)

// Read a whole file into the memory and store it as array of lines
func readLines(path string) (lines []string, err error) {
    var (
        file *os.File
        part []byte
        prefix bool
    )
    if file, err = os.Open(path); err != nil {
        return
    }
    defer file.Close()

    reader := bufio.NewReader(file)
    buffer := bytes.NewBuffer(make([]byte, 0))
    for {
        if part, prefix, err = reader.ReadLine(); err != nil {
            break
        }
        buffer.Write(part)
        if !prefix {
            lines = append(lines, buffer.String())
            buffer.Reset()
        }
    }
    if err == io.EOF {
        err = nil
    }
    return
}

func writeLines(lines []string, path string) (err error) {
    var (
        file *os.File
    )

    if file, err = os.Create(path); err != nil {
        return
    }
    defer file.Close()

    //writer := bufio.NewWriter(file)
    for _,item := range lines {
        //fmt.Println(item)
        _, err := file.WriteString(strings.TrimSpace(item) + "\n"); 
        //file.Write([]byte(item)); 
        if err != nil {
            //fmt.Println("debug")
            fmt.Println(err)
            break
        }
    }
    /*content := strings.Join(lines, "\n")
    _, err = writer.WriteString(content)*/
    return
}

func main() {
    lines, err := readLines("foo.txt")
    if err != nil {
        fmt.Println("Error: %s\n", err)
        return
    }
    for _, line := range lines {
        fmt.Println(line)
    }
    //array := []string{"7.0", "8.5", "9.1"}
    err = writeLines(lines, "foo2.txt")
    fmt.Println(err)
}
32
Bill.Zhuang

Vous pouvez utiliser os.File (qui implémente l'interface io.Reader ) avec le package bufio pour cela. Cependant, ces packages sont conçus pour une utilisation de mémoire fixe (quelle que soit la taille du fichier) et sont assez rapides.

Malheureusement, la lecture de tout le fichier dans la mémoire est un peu plus compliquée. Vous pouvez utiliser un bytes.Buffer pour joindre les parties de la ligne si elles dépassent la limite de ligne. Quoi qu'il en soit, je vous recommande d'essayer d'utiliser le lecteur de ligne directement dans votre projet (surtout si vous ne connaissez pas la taille du fichier texte!). Mais si le fichier est petit, l'exemple suivant peut vous suffire:

package main

import (
    "os"
    "bufio"
    "bytes"
    "fmt"
)

// Read a whole file into the memory and store it as array of lines
func readLines(path string) (lines []string, err os.Error) {
    var (
        file *os.File
        part []byte
        prefix bool
    )
    if file, err = os.Open(path); err != nil {
        return
    }
    reader := bufio.NewReader(file)
    buffer := bytes.NewBuffer(make([]byte, 1024))
    for {
        if part, prefix, err = reader.ReadLine(); err != nil {
            break
        }
        buffer.Write(part)
        if !prefix {
            lines = append(lines, buffer.String())
            buffer.Reset()
        }
    }
    if err == os.EOF {
        err = nil
    }
    return
}

func main() {
    lines, err := readLines("foo.txt")
    if err != nil {
        fmt.Println("Error: %s\n", err)
        return
    }
    for _, line := range lines {
        fmt.Println(line)
    }
}

Une autre alternative pourrait être d'utiliser io.ioutil.ReadAll pour lire le fichier complet en une fois et faire le découpage par ligne ensuite. Je ne vous donne pas un exemple explicite sur la façon d'écrire les lignes dans le fichier, mais c'est en gros un os.Create() suivi d'une boucle similaire à celle de l'exemple (voir main()) .

18
tux21b
func readToDisplayUsingFile1(f *os.File){
    defer f.Close()
    reader := bufio.NewReader(f)
    contents, _ := ioutil.ReadAll(reader)
    lines := strings.Split(string(contents), '\n')
}

ou

func readToDisplayUsingFile1(f *os.File){
    defer f.Close()
    slice := make([]string,0)

    reader := bufio.NewReader(f)

    for{

    str, err := reader.ReadString('\n')
    if err == io.EOF{
        break
    }

        slice = append(slice, str)
    }
3
Muhammad Soliman