it-swarm.com.de

Wie kann ich mit Go von / in eine Datei lesen / schreiben?

Ich habe versucht, Go auf eigene Faust zu lernen, aber ich war ratlos darüber, gewöhnliche Dateien zu lesen und in sie zu schreiben.

Ich kann bis zu inFile, _ := os.Open(INFILE, 0, 0) gehen, aber der Inhalt der Datei ist eigentlich nicht sinnvoll, da die Lesefunktion ein []byte als Parameter.

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

Lassen Sie uns eine Go 1-kompatible Liste aller Möglichkeiten zum Lesen und Schreiben von Dateien in Go erstellen.

Da sich die Datei-API kürzlich geändert hat und die meisten anderen Antworten mit Go 1 nicht funktionieren. Außerdem fehlt bufio, was meiner Meinung nach wichtig ist.

In den folgenden Beispielen kopiere ich eine Datei, indem ich sie 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 Und os.Create Verwendet, die praktische Wrapper um os.OpenFile Sind. Normalerweise müssen wir OpenFile nicht direkt aufrufen.

Beachten Sie die Behandlung von EOF. Read versucht, buf bei jedem Aufruf zu füllen, und gibt io.EOF als Fehler zurück, wenn es dabei das Dateiende erreicht. In diesem Fall enthält buf weiterhin Daten. Nachfolgende Aufrufe von Read geben Null als Anzahl der gelesenen Bytes und dasselbe io.EOF Als Fehler zurück. Jeder andere Fehler führt zu einer Panik.

Mit 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 fungiert hier nur als Puffer, da wir nicht viel mit Daten zu tun haben. In den meisten anderen Situationen (insbesondere bei Textdateien) ist bufio sehr nützlich, wenn Sie uns eine nette API zum einfachen und flexiblen Lesen und Schreiben geben, während die Pufferung im Hintergrund erfolgt.

Mit 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)
    }
}

Einfach wie Torte! Verwenden Sie es jedoch nur, wenn Sie sicher sind, dass Sie nicht mit großen Dateien zu tun haben.

452
Mostafa

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)
}
47
Piotr

Mit 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 keine Lust haben, das Rad neu zu erfinden, wird der io.Copy und io.CopyN kann dir gut dienen. Wenn Sie überprüfen Sie die Quelle der io.Copy-Funktion, handelt es sich nur um eine der Mostafa-Lösungen (die 'grundlegende', die tatsächlich in der Go-Bibliothek enthalten ist). Sie verwenden jedoch einen wesentlich größeren Puffer als er.

27
user7610

[]byte Ist ein Slice (ähnlich einem Teilstring) eines gesamten Bytearrays oder eines Teils davon. Stellen Sie sich das Slice als eine Wertestruktur mit einem verborgenen Zeigerfeld vor, mit dem das System alle oder einen Teil eines Arrays (das Slice) lokalisieren und darauf zugreifen kann, sowie Feldern für die Länge und Kapazität des Slices, auf die Sie mit dem Befehl len() und cap() Funktionen.

Hier ist ein Starter-Kit, das eine Binärdatei liest und druckt. Sie müssen den Literalwert inName ändern, um auf eine kleine Datei auf Ihrem System zu verweisen.

package main
import (
    "fmt";
    "os";
)
func main()
{
    inName := "file-rw.bin";
    inPerm :=  0666;
    inFile, inErr := os.Open(inName, os.O_RDONLY, inPerm);
    if inErr == nil {
        inBufLen := 16;
        inBuf := make([]byte, inBufLen);
        n, inErr := inFile.Read(inBuf);
        for inErr == nil {
            fmt.Println(n, inBuf[0:n]);
            n, inErr = inFile.Read(inBuf);
        }
    }
    inErr = inFile.Close();
}
10
peterSO

Mit neueren Go-Versionen ist das Lesen/Schreiben in/aus Dateien einfach. So lesen Sie aus einer Datei:

package main

import (
    "fmt"
    "io/ioutil"
)

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

So schreiben Sie 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 (erstellen Sie eine neue Datei, wenn sie nicht vorhanden war).

8
Salvador Dali

Versuche dies:

package main

import (
  "io"; 
  )


func main() {
  contents,_ := io.ReadFile("filename");
  println(string(contents));
  io.WriteFile("filename", contents, 0644);
}
7
marketer

Die Read-Methode akzeptiert einen Byte-Parameter, da dies der Puffer ist, in den gelesen wird. In manchen Kreisen ist dies eine gängige Redewendung und macht Sinn, wenn man darüber nachdenkt.

Auf diese Weise können Sie bestimmen, wie viele Bytes vom Lesegerät gelesen werden, und die Rückgabe untersuchen, um festzustellen, wie viele Bytes tatsächlich gelesen wurden, und Fehler angemessen behandeln.

Wie andere in ihren Antworten darauf hingewiesen haben, ist bufio wahrscheinlich das, was Sie zum Lesen aus den meisten Dateien benötigen.

Ich werde noch einen weiteren Hinweis hinzufügen, da er wirklich nützlich ist. Das Lesen einer Zeile aus einer Datei erfolgt am besten nicht mit der ReadLine-Methode, sondern mit der ReadBytes- oder ReadString-Methode.

1
Jeremy Wall

Wenn Sie sich nur die Dokumentation ansehen, sollten Sie einfach einen Puffer vom Typ [] Byte deklarieren und an read übergeben, der dann bis zu so viele Zeichen liest und die Anzahl der tatsächlich gelesenen Zeichen (und einen Fehler) zurückgibt.

Die Dokumente sagen

Read liest bis zu len (b) Bytes aus der Datei. Es gibt die Anzahl der gelesenen Bytes und gegebenenfalls einen Fehler zurück. EOF wird durch eine Nullzählung angezeigt, wobei err auf EOF gesetzt ist.

Geht das nicht

EDIT: Ich denke, Sie sollten auch die Reader/Writer-Schnittstellen verwenden, die im bufio -Paket deklariert sind, anstatt zu verwenden. os Paket.

1
Hannes Ovrén