读取刚刚写入临时文件的数据

ptd*_*ker 0 go temporary-files

在 Go 中,我尝试将数据写入临时文件,然后转身读取该文件,但没有成功。下面是一个精简的测试程序。我已通过检查临时文件验证数据是否已写入文件。所以,至少我知道数据正在进入文件。我只是无法读出它。

提前谢谢你的帮助

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)
    }
}
Run Code Online (Sandbox Code Playgroud)

p9s*_*9sh 5

ioutil.TempFile创建一个临时文件并打开该文件进行读写并返回结果*os.File(文件描述符)。因此,当您在文件内写入时,指针将移动到该偏移量,即当前位于文件末尾。但是,当您的要求是从文件中读取时,您需要Seek使用方法返回到开头或所需的偏移量*os.File.Seek。因此,添加tmpFile.Seek(0, 0)将为您提供所需的行为。

另外,作为一个好的做法,不要忘记关闭文件。请注意,我使用了defer tmpFile.Close()在退出之前关闭文件的方法。

请参考以下示例:

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)
    }
}
Run Code Online (Sandbox Code Playgroud)

更新:OP 的评论:

鉴于删除实际文件也被推迟,是否需要推迟关闭?如果是这样,我想推迟的顺序很重要。

所以,这是一个很好的问题。因此基本的经验法则是关闭文件然后删除。因此,甚至可以先删除然后再关闭它,但这取决于操作系统。

如果您参考C++ 的文档

如果文件当前由当前进程或另一个进程打开,则此函数的行为是实现定义的(特别是,POSIX 系统取消链接文件名,尽管文件系统空间不会被回收,即使这是到该文件的最后一个硬链接)文件直到最后一个运行的进程关闭该文件为止,Windows不允许删除该文件)

因此,在 Windows 上,如果您尝试先删除它而不关闭它,那么这肯定是一个问题。

因此,由于defer是堆叠的,所以执行顺序是

defer os.Remove(tmpFile.Name()) // Called 2nd
defer tmpFile.Close() // Called 1st
Run Code Online (Sandbox Code Playgroud)