Reading data just written to a temp file

两盒软妹~` 提交于 2021-02-05 12:27:04

问题


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 data are being written to the file by inspecting the temporary file. So, at least I know that data are making it into the file. I just am then unable to read it out.

Thank you for your help in advance

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)
    }
    fmt.Println("Created temp file: ", tmpFile.Name())
    //  defer os.Remove(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")
    s := bufio.NewScanner(tmpFile)
    for s.Scan() {
        fmt.Println(s.Text())
    }
    err = s.Err()
    if err != nil {
        log.Fatal("error reading temp file", err)
    }
}

回答1:


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



回答2:


package main

import (
    "fmt"
    "io/ioutil"
    "log"
)

func main() {
    content, err := ioutil.ReadFile("testdata/hello")
    if err != nil {
        log.Fatal(err)
    }

    fmt.Printf("File contents: %s", content)

according to the official golang docs.



来源:https://stackoverflow.com/questions/64146997/reading-data-just-written-to-a-temp-file

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!