Golang 生成带有扩展名的唯一文件名



我想在 Golang 中生成带有扩展名的唯一文件名。 非常类似于ioutil。临时文件,仅接受前缀。

这在论坛 https://groups.google.com/forum/#!topic/golang-nuts/PHgye3Hm2_0 中被多次提出,Go似乎非常打算不将该功能添加到TempFile中。

那么建议的

处理方法是什么? 我应该只复制/粘贴 TempFile 代码并添加后缀参数吗?

更新(2020:原始答案来自 2015 年)

正如Lax的回答中所指出的,Go 1.11(2018年4月)已将前缀TempFile更改为模式。

请参阅问题 4896 之后从 CL 105675 提交 191efbc

TempFile用户需要能够提供后缀,尤其是 当使用赋予语义意义的操作系统时 文件扩展名,例如视窗。
重命名文件以在事后包含扩展名是不够的,因为它可能会导致争用条件。

如果给TempFile的字符串包含"*",则随机字符串 替换"*"。

例如 "myname.*.bat" 将导致随机 文件名,如"myname.123456.bat"。

如果没有包含"*",则 保留旧行为,并将随机数字附加到 结束。

如果包含多个"*",则替换最后一个,因此 允许病理程序员创建文件名,例如 "foo*.123456.bat",但不是"foo.123456.*.bat"


原始答案 (2015)

我应该只复制/粘贴 TempFile 代码并添加后缀参数吗?

那将是一种方式。
另一种方法是进行快速 - 粗略的 - 实现,如本项目所示:

// TempFileName generates a temporary filename for use in testing or whatever
func TempFileName(prefix, suffix string) string {
    randBytes := make([]byte, 16)
    rand.Read(randBytes)
    return filepath.Join(os.TempDir(), prefix+hex.EncodeToString(randBytes)+suffix)
}

正如 James Henstridge 在下面评论的那样,这是一个粗略的函数:

例如,该函数可以返回已经存在的文件名。这样的 API 应该通过使用O_CREAT | O_EXCL打开文件来创建文件,以确保在决定名称和创建文件之间没有其他人创建文件。

上面的粗略函数仅说明了使用 rand.Read() 生成文件名。

但其他检查都在io/ioutil/tempfile.go.
3of3 建议在 math.rand 中使用函数,而不是在 io/ioutil/tempfile.go 中复制随机数生成器。

从 Go 1.16(2021 年 2 月)开始,您可以使用os.CreateTemp

package main
import "os"
func main() {
   dirs := []string{"", "."}
   for _, dir := range dirs {
      f, err := os.CreateTemp(dir, "*.txt")
      if err != nil {
         panic(err)
      }
      defer f.Close()
      println(f.Name())
   }
}

结果:

C:WindowsTEMP163991747.txt
.2499233563.txt

https://godocs.io/os#CreateTemp

看看 https://github.com/tink-ab/tempfile。它基本上是标准库提供的内容,但同时支持前缀和后缀。

对于任何最近阅读此线程的人来说,截至目前(2020 年 4 月),ioutil.TempFile 同时处理前缀和后缀。

从其文档中:

临时文件在

目录目录中创建一个新的临时文件, 打开文件进行读取和写入,并返回生成的*os.File 。 文件名是通过采用模式并添加随机生成的 字符串到最后。如果模式包含"*",则随机字符串 替换最后一个" * "。

因此,传递"prefix-*-suffix"作为pattern参数将产生预期的行为。

最新更新