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 in letzter Zeit geändert hat und die meisten anderen Antworten mit Go 1 nicht funktionieren, fehlt ihnen auch, bufio
was meiner Meinung nach wichtig ist.
In den folgenden Beispielen kopiere ich eine Datei, indem ich daraus 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 verwendet os.Open
und os.Create
welche sind praktische Wrapper herum os.OpenFile
. Wir müssen normalerweise nicht OpenFile
direkt anrufen .
Beachten Sie die Behandlung von EOF. Read
versucht buf
bei jedem Aufruf zu füllen und gibt io.EOF
als Fehler zurück, wenn dabei das Dateiende erreicht wird. In diesem Fall buf
werden weiterhin Daten gespeichert. Nachfolgende Aufrufe von geben Read
Null als Anzahl der gelesenen Bytes und io.EOF
als Fehler zurück. Jeder andere Fehler führt zu einer Panik.
Verwenden 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
fungiert hier nur als Puffer, weil wir nicht viel mit Daten zu tun haben. In den meisten anderen Situationen (insbesondere bei Textdateien) bufio
ist dies sehr nützlich, da wir eine schöne API zum einfachen und flexiblen Lesen und Schreiben haben, während die Pufferung hinter den Kulissen erfolgt.
Verwenden 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)
}
}
Einfach wie Torte! Verwenden Sie es jedoch nur, wenn Sie sicher sind, dass Sie nicht mit großen Dateien zu tun haben.
panic("error in writing")
) ist also nicht erforderlich.Das ist eine gute Version:
quelle
0x777
ist falsch. In jedem Fall sollte es eher wie0644
oder0755
(oktal, nicht hex) sein.Verwenden von
io.Copy
Wenn Sie das Rad nicht neu erfinden möchten, kann das
io.Copy
undio.CopyN
Ihnen gute Dienste leisten . Wenn Sie die Quelle der io.Copy-Funktion überprüfen , handelt es sich nur um eine der Mostafa-Lösungen (eigentlich die 'grundlegende'), die in der Go-Bibliothek enthalten sind. Sie verwenden jedoch einen wesentlich größeren Puffer als er.quelle
w.Sync()
nach demio.Copy(w, r)
io.Copy()
schreiben , werden nur die Daten geschrieben, mit denen Sie sie füttern. Wenn also eine vorhandene Datei mehr Inhalt enthält, wird sie nicht entfernt, was zu einer beschädigten Datei führen kann.w, err := os.Create("output.txt")
, geschieht das , was Sie beschreiben, nicht, da "Erstellen die benannte Datei erstellt oder abschneidet. Wenn die Datei bereits vorhanden ist, wird sie abgeschnitten." golang.org/pkg/os/#Create .Mit neueren Go-Versionen ist das Lesen / Schreiben in / aus einer Datei einfach. So lesen Sie aus einer Datei:
So schreiben Sie in eine Datei:
Dadurch wird der Inhalt einer Datei überschrieben (erstellen Sie eine neue Datei, wenn diese nicht vorhanden war).
quelle
[]byte
ist ein Slice (ähnlich einem Teilstring) eines gesamten oder eines Teils eines Byte-Arrays. Stellen Sie sich das Slice als eine Wertestruktur mit einem versteckten Zeigerfeld vor, mit dem das System ein Array (das Slice) ganz oder teilweise lokalisieren und darauf zugreifen kann, sowie Felder für die Länge und Kapazität des Slice, auf die Sie mit den Funktionenlen()
und zugreifencap()
können .Hier ist ein funktionierendes Starter-Kit für Sie, das eine Binärdatei liest und druckt. Sie müssen den
inName
Literalwert ändern , um auf eine kleine Datei auf Ihrem System zu verweisen.quelle
if
Versuche dies:
quelle
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
Funktioniert das nicht
EDIT: Außerdem denke ich, dass Sie vielleicht die im bufio- Paket deklarierten Reader / Writer-Schnittstellen verwenden sollten , anstatt das os- Paket zu verwenden.
quelle
Die Read-Methode verwendet einen Byte-Parameter, da dies der Puffer ist, in den gelesen wird. In manchen Kreisen ist es eine gängige Redewendung und macht Sinn, wenn man darüber nachdenkt.
Auf diese Weise können Sie bestimmen, wie viele Bytes vom Reader gelesen werden, und die Rückgabe überprüfen, um festzustellen, wie viele Bytes tatsächlich gelesen wurden, und Fehler entsprechend behandeln.
Wie andere in ihren Antworten gezeigt haben, ist Bufio wahrscheinlich das, was Sie zum Lesen aus den meisten Dateien wünschen.
Ich werde noch einen Hinweis hinzufügen, da es 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.
quelle