373 Stimmen

Wie man mit Go von/auf eine Datei liest/schreibt

Ich habe versucht, Go auf eigene Faust zu lernen, aber ich war ratlos, als ich versuchte, von normalen Dateien zu lesen und in sie zu schreiben.

Ich kann so weit kommen wie inFile, _ := os.Open(INFILE, 0, 0) aber es macht keinen Sinn, den Inhalt der Datei abzurufen, denn die Lesefunktion benötigt eine []byte als Parameter.

func (file *File) Read(b []byte) (n int, err Error)

578voto

Mostafa Punkte 24982

Lassen Sie uns eine Go 1-kompatible Liste aller Möglichkeiten erstellen, Dateien in Go zu lesen und zu schreiben.

Weil sich die Datei-API vor kurzem geändert hat und die meisten anderen Antworten nicht mit Go 1 funktionieren. Sie vermissen auch bufio was IMHO wichtig ist.

In den folgenden Beispielen kopiere ich eine Datei, indem ich aus ihr lese und in die Zieldatei schreibe.

Beginnen Sie mit den Grundlagen

package main

import (
    "io"
    "os"
)

func main() {
    // open input file
    fi, err := os.Open("input.txt")
    if err != nil {
        panic(err)
    }
    // close fi on exit and check for its returned error
    defer func() {
        if err := fi.Close(); err != nil {
            panic(err)
        }
    }()

    // open output file
    fo, err := os.Create("output.txt")
    if err != nil {
        panic(err)
    }
    // close fo on exit and check for its returned error
    defer func() {
        if err := fo.Close(); err != nil {
            panic(err)
        }
    }()

    // make a buffer to keep chunks that are read
    buf := make([]byte, 1024)
    for {
        // read a chunk
        n, err := fi.Read(buf)
        if err != nil && err != io.EOF {
            panic(err)
        }
        if n == 0 {
            break
        }

        // write a chunk
        if _, err := fo.Write(buf[:n]); err != nil {
            panic(err)
        }
    }
}

Hier habe ich os.Open y os.Create die praktische Umhüllungen sind für os.OpenFile . Normalerweise müssen wir nicht anrufen OpenFile direkt.

Hinweis zur Behandlung von EOF. Read versucht zu füllen buf bei jedem Aufruf, und gibt io.EOF als Fehler, wenn er dabei das Ende der Datei erreicht. In diesem Fall buf noch Daten enthalten. Folgerichtige Aufrufe von Read gibt Null als Anzahl der gelesenen Bytes zurück und dasselbe io.EOF als Fehler. Jeder andere Fehler führt zu einer Panik.

Verwendung von bufio

package main

import (
    "bufio"
    "io"
    "os"
)

func main() {
    // open input file
    fi, err := os.Open("input.txt")
    if err != nil {
        panic(err)
    }
    // close fi on exit and check for its returned error
    defer func() {
        if err := fi.Close(); err != nil {
            panic(err)
        }
    }()
    // make a read buffer
    r := bufio.NewReader(fi)

    // open output file
    fo, err := os.Create("output.txt")
    if err != nil {
        panic(err)
    }
    // close fo on exit and check for its returned error
    defer func() {
        if err := fo.Close(); err != nil {
            panic(err)
        }
    }()
    // make a write buffer
    w := bufio.NewWriter(fo)

    // make a buffer to keep chunks that are read
    buf := make([]byte, 1024)
    for {
        // read a chunk
        n, err := r.Read(buf)
        if err != nil && err != io.EOF {
            panic(err)
        }
        if n == 0 {
            break
        }

        // write a chunk
        if _, err := w.Write(buf[:n]); err != nil {
            panic(err)
        }
    }

    if err = w.Flush(); err != nil {
        panic(err)
    }
}

bufio dient hier nur als Puffer, denn wir haben nicht viel mit Daten zu tun. In den meisten anderen Situationen (besonders bei Textdateien) bufio ist sehr nützlich, da es uns eine schöne API für einfaches und flexibles Lesen und Schreiben, während es im Hintergrund die Pufferung übernimmt.


Nota: Der folgende Code ist für ältere Go-Versionen (Go 1.15 und früher). Die Dinge haben sich geändert. Für den neuen Weg, schauen Sie sich an diese Antwort .

Verwendung von ioutil

package main

import (
    "io/ioutil"
)

func main() {
    // read the whole file at once
    b, err := ioutil.ReadFile("input.txt")
    if err != nil {
        panic(err)
    }

    // write the whole body at once
    err = ioutil.WriteFile("output.txt", b, 0644)
    if err != nil {
        panic(err)
    }
}

Ein Kinderspiel! Verwenden Sie es aber nur, wenn Sie sicher sind, dass Sie es nicht mit großen Dateien zu tun haben.

58voto

Piotr Punkte 575

Dies ist eine gute Version:

package main

import (
  "io/ioutil"; 
  )

func main() {
  contents,_ := ioutil.ReadFile("plikTekstowy.txt")
  println(string(contents))
  ioutil.WriteFile("filename", contents, 0644)
}

52voto

Inanc Gumus Punkte 20769

Neuer Weg

Beginnend mit Go 1.16, verwenden Sie os.ReadFile um die Datei in den Speicher zu laden, und mit os.WriteFile um aus dem Speicher in eine Datei zu schreiben ( ioutil.ReadFile ruft nun os.ReadFile ).

Seien Sie vorsichtig mit dem os.ReadFile weil es die gesamte Datei in den Speicher liest.

package main

import "os"

func main() {
    b, err := os.ReadFile("input.txt")
    if err != nil {
        log.Fatal(err)
    }

    // `b` contains everything your file has.
    // This writes it to the Standard Out.
    os.Stdout.Write(b)

    // You can also write it to a file as a whole.
    err = os.WriteFile("destination.txt", b, 0644)
    if err != nil {
        log.Fatal(err)
    }
}

46voto

user7610 Punkte 20682

Verwendung von io.Copy

package main

import (
    "io"
    "log"
    "os"
)

func main () {
    // open files r and w
    r, err := os.Open("input.txt")
    if err != nil {
        panic(err)
    }
    defer r.Close()

    w, err := os.Create("output.txt")
    if err != nil {
        panic(err)
    }
    defer w.Close()

    // do the actual work
    n, err := io.Copy(w, r)
    if err != nil {
        panic(err)
    }
    log.Printf("Copied %v bytes\n", n)
}

Wenn Sie das Rad nicht neu erfinden wollen, können Sie die io.Copy y io.CopyN kann Ihnen gute Dienste leisten. Wenn Sie Prüfen Sie die Quelle der Funktion io.Copy ist nichts anderes als eine der Lösungen von Mostafa (die "grundlegende", um genau zu sein), die in der Go-Bibliothek enthalten ist. Sie verwenden allerdings einen wesentlich größeren Puffer als er.

23voto

Salvador Dali Punkte 197375

Mit neueren Go-Versionen ist das Lesen und Schreiben in/aus einer Datei einfach. Um aus einer Datei zu lesen:

package main

import (
    "fmt"
    "io/ioutil"
)

func main() {
    data, err := ioutil.ReadFile("text.txt")
    if err != nil {
        return
    }
    fmt.Println(string(data))
}

Zum Schreiben in eine Datei:

package main

import "os"

func main() {
    file, err := os.Create("text.txt")
    if err != nil {
        return
    }
    defer file.Close()

    file.WriteString("test\nhello")
}

Dadurch wird der Inhalt einer Datei überschrieben (es wird eine neue Datei erstellt, falls sie noch nicht vorhanden war).

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X