質問

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メソッドを使用するのが最適です。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top