读取刚刚写入临时文件的数据
Reading data just written to a temp file
在 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)
}
}
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)
根据官方 golang 文档。
ioutil.TempFile
创建一个临时文件并打开文件进行读写,returns 结果 *os.File
(文件描述符)。因此,当您在文件内部写入时,指针会移动到该偏移量,即,它当前位于文件末尾。
但是当您的要求是从文件中读取时,您需要使用 *os.File.Seek
方法 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 的评论:
Is the deferred close needed given that deleting the actual file is also deferred? If so, I imagine order of deferral would matter.
所以,这是一个很好的问题。所以基本的经验法则是关闭文件然后删除。因此,甚至可以先删除然后再关闭它,但那是 OS-dependent.
如果你参考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)
因此,在 Windows,如果您尝试先删除它而不关闭它,那肯定是个问题。
因此,由于 defer
是堆叠的,因此执行顺序将是
defer os.Remove(tmpFile.Name()) // Called 2nd
defer tmpFile.Close() // Called 1st
在 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)
}
}
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)
根据官方 golang 文档。
ioutil.TempFile
创建一个临时文件并打开文件进行读写,returns 结果 *os.File
(文件描述符)。因此,当您在文件内部写入时,指针会移动到该偏移量,即,它当前位于文件末尾。
但是当您的要求是从文件中读取时,您需要使用 *os.File.Seek
方法 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 的评论:
Is the deferred close needed given that deleting the actual file is also deferred? If so, I imagine order of deferral would matter.
所以,这是一个很好的问题。所以基本的经验法则是关闭文件然后删除。因此,甚至可以先删除然后再关闭它,但那是 OS-dependent.
如果你参考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)
因此,在 Windows,如果您尝试先删除它而不关闭它,那肯定是个问题。
因此,由于 defer
是堆叠的,因此执行顺序将是
defer os.Remove(tmpFile.Name()) // Called 2nd
defer tmpFile.Close() // Called 1st