47348


任意のファイルを指定したサイズに分割しようと、以下のように書きました。  
（エラー処理は省略しています）

[code]

    package main
    
    import (
        "io"
        "os"
        "strconv"
    )
    
    func main() {
    
        src := "inputfile"
    
        in, _ := os.Open(src)
        defer in.Close()
    
        // 分割後ファイルのサイズ
        const size = 2
    
        var offset int64 = 0
        cnt := 1
    
        for {
            r := io.NewSectionReader(in, offset, size)
    
            out, _ := os.Create(src + "_" + strconv.Itoa(cnt))
            defer out.Close()
    
            n, _ := io.Copy(out, r)
    
            if n == 0 {
                break
            }
    
            offset += size
            cnt += 1
        }
    }
    
[/code]

実行すると、以下のように分割はできたのですが、ゼロバイトの余計なファイルが作られてしまいました。原因は分割後のファイルを`os.Create`してから中身を書き込んでいるためです。

[code]

    2018/08/08  15:16                 7 inputfile
    2018/08/08  16:09                 2 inputfile_1
    2018/08/08  16:09                 2 inputfile_2
    2018/08/08  16:09                 2 inputfile_3
    2018/08/08  16:09                 1 inputfile_4
    2018/08/08  16:09                 0 inputfile_5
    
[/code]

そこで、事前に分割前のファイルサイズを調べておいてからそのサイズを使ってループを抜ける、という方法も考えたのですが、別の方法として、`SectionReader`を作った時点でReadできる残バイトがあるかどうかを確認すればよいと思い、以下のような判定を追加しました。

[code]

    for {
        r := io.NewSectionReader(in, offset, size)
    
        // 読み込めるバイトが残っているか確認する
        buf := make([]byte, 1)
        bn, _ := r.Read(buf)
        if bn == 0 {
            break
        }
        // ファイルポインタを先頭に戻す
        r.Seek(0, 0)
    
[/code]

これで一応は達成できたのですが、そもそも「Readできる残バイトがあるかどうか」を知る一般的？な方法はありますでしょうか。


CC BY-SA 4.0
2018-08-08T07:55:50.300
47345
2018-08-08T09:01:50.787
19759
question
go
io.SectionReaderで、Readできる残バイトがあるかどうかを確認する方法


`bufio.Peek()` を使ってみるのはどうでしょうか。

[code]

    for {
        r := bufio.NewReader(io.NewSectionReader(in, offset, size))
        if _, err := r.Peek(1); err == io.EOF {
            break
        }
    
        out, _ := os.Create(src + "_" + strconv.Itoa(cnt))
        defer out.Close()
    
        io.Copy(out, r)
    
        offset += size
        cnt += 1
    }
    
[/code]


CC BY-SA 4.0
2018-08-08T09:01:50.787
47348
2018-08-08T09:01:50.787
47345
answer