Reading data just written to a temp file

前端 未结 2 1816
广开言路
广开言路 2021-01-29 10:13

In Go, I am trying to write data to a temp file that I then turn around and read but have not been successful. Below is a stripped down test program. I have verified that the

2条回答
  •  [愿得一人]
    2021-01-29 11:14

    ioutil.TempFile creates a temp file and opens the file for reading and writing and returns the resulting *os.File (file descriptor). So when you're writing inside the file, the pointer is moved to that offset, i.e., it's currently at the end of the file. But as your requirement is read from the file, you need to Seek back to the beginning or wherever desired offset using *os.File.Seek method. So, adding tmpFile.Seek(0, 0) will give you the desired behaviour.

    Also, as a good practice, do not forget to close the file. Notice I've used defer tmpFile.Close() which closes the file before exiting.

    Refer the following example:

    package main
    
    import (
        "bufio"
        "fmt"
        "io/ioutil"
        "log"
        "os"
        "path/filepath"
    )
    
    func main() {
        tmpFile, err := ioutil.TempFile("", fmt.Sprintf("%s-", filepath.Base(os.Args[0])))
        if err != nil {
            log.Fatal("Could not create temporary file", err)
        }
        defer tmpFile.Close()
    
        fmt.Println("Created temp file: ", tmpFile.Name())
    
        fmt.Println("Writing some data to the temp file")
        if _, err = tmpFile.WriteString("test data"); err != nil {
            log.Fatal("Unable to write to temporary file", err)
        } else {
            fmt.Println("Data should have been written")
        }
    
        fmt.Println("Trying to read the temp file now")
    
        // Seek the pointer to the beginning
        tmpFile.Seek(0, 0)
        s := bufio.NewScanner(tmpFile)
        for s.Scan() {
            fmt.Println(s.Text())
        }
        if err = s.Err(); err != nil {
            log.Fatal("error reading temp file", err)
        }
    }
    

    Update: Comment from OP:

    Is the deferred close needed given that deleting the actual file is also deferred? If so, I imagine order of deferral would matter.

    So, that's a nice question. So the basic rule of thumb would be to close the file and then remove. So, it might even be possible to delete first and later close it, but that is OS-dependent.

    If you refer C++'s doc:

    If the file is currently open by the current or another process, the behavior of this function is implementation-defined (in particular, POSIX systems unlink the file name, although the file system space is not reclaimed even if this was the last hardlink to the file until the last running process closes the file, Windows does not allow the file to be deleted)

    So, on Windows, that's a problem for sure if you try deleting it first without closing it.

    So, as defer's are stacked, so the order of execution would be

    defer os.Remove(tmpFile.Name()) // Called 2nd
    defer tmpFile.Close() // Called 1st
    

提交回复
热议问题