質問
Goを独力で学習しようとしていますが、通常のファイルの読み取りと書き込みを試みることに困惑しています。
inFile、_:= os.Open(INFILE、0、0)
まで取得できますが、実際にはファイルの内容を取得しても意味がありません。パラメータとして [] byte
を受け取ります。
func (file *File) Read(b []byte) (n int, err Error)
解決
Goでファイルを読み書きするすべての方法のGo 1互換リストを作成しましょう。
ファイルAPIが最近変更されたため、他のほとんどの回答はGo 1では動作しません。また、重要なIMHOである bufio
も見逃しています。
次の例では、ファイルを読み取って宛先ファイルに書き込むことでファイルをコピーします。
基本から始める
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)
}
}
}
ここでは、 os.Open
の便利なラッパーである os.Open
と os.Create
を使用しました。通常、 OpenFile
を直接呼び出す必要はありません。
EOFの処理に関する通知。 Read
は、呼び出しごとに buf
を埋めようとし、ファイルの終わりに達すると io.EOF
をエラーとして返します。この場合、 buf
は引き続きデータを保持します。その後の Read
の呼び出しは、読み取ったバイト数としてゼロを返し、エラーと同じ io.EOF
を返します。その他のエラーはパニックにつながります。
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
は、ここではバッファとして機能しているだけです。データとはあまり関係がないからです。他のほとんどの状況(特にテキストファイル)では、 bufio
はを提供することで非常に便利です。背後でのバッファリングを処理しながら、簡単かつ柔軟に読み書きを行うための優れたAPI 。
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)
}
}
パイのように簡単!ただし、大きなファイルを処理していないことが確実な場合にのみ使用してください。
他のヒント
これは良いバージョンです:
package main
import (
"io/ioutil";
)
func main() {
contents,_ := ioutil.ReadFile("plikTekstowy.txt")
println(string(contents))
ioutil.WriteFile("filename", contents, 0644)
}
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)
}
車輪を再発明したくない場合は、 io.Copy
と io.CopyN
が役立ちます。 io.Copy関数のソースを確認する場合、 Goライブラリにパッケージ化されたMostafaのソリューション(実際には「基本」ソリューション)の1つにすぎません。しかし、彼らは彼よりもかなり大きなバッファーを使用しています。
[] byte
は、バイト配列の全体または一部のスライス(サブストリングに類似)です。スライスは、配列(スライス)のすべてまたは一部を検索してアクセスするためのシステムの隠しポインターフィールド、および len()
および cap()
関数。
これは、バイナリファイルの読み取りと印刷を行うための実用的なスターターキットです。システム上の小さなファイルを参照するには、 inName
リテラル値を変更する必要があります。
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();
}
新しいGoバージョンでは、ファイルの読み取り/書き込みが簡単です。ファイルから読み取るには:
package main
import (
"fmt"
"io/ioutil"
)
func main() {
data, err := ioutil.ReadFile("text.txt")
if err != nil {
return
}
fmt.Println(string(data))
}
ファイルに書き込むには:
package main
import "os"
func main() {
file, err := os.Create("text.txt")
if err != nil {
return
}
defer file.Close()
file.WriteString("test\nhello")
}
これにより、ファイルの内容が上書きされます(存在しない場合は新しいファイルを作成します)。
これを試してください:
package main
import (
"io";
)
func main() {
contents,_ := io.ReadFile("filename");
println(string(contents));
io.WriteFile("filename", contents, 0644);
}
ドキュメントを見るだけで、[] byte型のバッファを宣言してreadに渡すだけで、その数の文字まで読み取り、実際に読み取った文字数(およびエラー)を返すように思えます。
ドキュメントの発言
Readは、ファイルから最大len(b)バイトを読み取ります。読み込まれたバイト数とエラーがあればそれを返します。 EOFは、errがEOFに設定されたゼロカウントによって通知されます。
それは機能しませんか?
編集:また、 os パッケージを使用する代わりに、 bufio パッケージで宣言されているReader / Writerインターフェイスを使用する必要があると思います。
Readメソッドは、それが読み込むバッファであるため、byteパラメーターを取ります。一部のサークルでは一般的なイディオムであり、考えてみると意味があります。
この方法により、リーダーが読み取るバイト数を決定し、戻り値を調べて実際に読み取られたバイト数を確認し、エラーを適切に処理できます。
他の人が答えを指摘しているように、bufioはおそらくほとんどのファイルから読みたいものです。
本当に役立つので、もう1つヒントを追加します。ファイルから行を読み取るには、ReadLineメソッドではなく、ReadBytesまたはReadStringメソッドを使用するのが最適です。