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

Go 读取刚刚写入临时文件的数据,go,temporary-files,Go,Temporary Files,在Go中,我试图将数据写入一个临时文件,然后将其转过来读取,但没有成功。下面是一个精简的测试程序。我已通过检查临时文件来验证数据是否正在写入文件。所以,至少我知道数据正在进入文件。我只是当时读不出来 提前谢谢你的帮助 package main import ( "bufio" "fmt" "io/ioutil" "log" "os" "p

在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)
    }
}

根据官方的golang文档。

ioutil.TempFile
创建一个临时文件,打开该文件进行读写,并返回生成的
*os.file
(文件描述符)。因此,当您在文件中写入时,指针将移动到该偏移量,即,它当前位于文件的末尾。 但是,当从文件中读取您的需求时,您需要使用
*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)
    }
}
更新: OP的评论:

考虑到删除实际文件也会延迟,是否需要延迟关闭?如果是这样,我想推迟的顺序会很重要

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

如果你提到:

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

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

因此,由于延迟是堆叠的,因此执行顺序将是

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

在您写入数据文件后,指针指向文件的结尾。您必须查找文件的开头才能读取您所写入的内容。使用tmpFile.SeekHe希望使用相同的程序来执行此操作。我想说这不是正确的答案w.r.t问题。谢谢,@shmsr。这非常有效。如果删除ac,是否需要延迟关闭最终文件也被推迟了?如果是这样,我想推迟的顺序会很重要。我很高兴这个答案有帮助。是的,我已经更新了我的答案,以消除您的其他疑虑。请告诉我是否有帮助?:)
defer os.Remove(tmpFile.Name()) // Called 2nd
defer tmpFile.Close() // Called 1st