如何在Go语言中获取文件长度?

118

我查看了 golang.org/pkg/os/#File,但仍然不清楚。 似乎没有办法获取文件长度,我错过了什么吗?

如何在Go中获取文件长度?

4个回答

168

(*os.File).Stat()会返回一个 os.FileInfo 值,它有一个 Size() 方法。所以,假设有一个文件 f,那么代码就可以这样写:

f.Stat().Size()
fi, err := f.Stat()
if err != nil {
  // Could not obtain stat, handle error
}

fmt.Printf("The file is %d bytes long", fi.Size())

121
如果您不想打开文件,可以直接调用 os.Stat
fi, err := os.Stat("/path/to/file")
if err != nil {
    return err
}
// get the size
size := fi.Size()

20
稍微详细一些的答案:
file, err := os.Open( filepath ) 
if err != nil {
    log.Fatal(err)
}
fi, err := file.Stat()
if err != nil {
    log.Fatal(err)
}
fmt.Println( fi.Size() )

9
Stat() 之前加上 defer file.Close() 可能会更好吧? - Timmmm
2
@Timmmm 是的 - 但由于这是一个代码片段,我们不能假设 fi io.Reader 没有被传递到其他地方,因此关闭它可能是妄自尊大的。 - colm.anseo
这通常是获取文件大小的正确方法,您将在检查其大小后不久处理该文件。在完成文件操作之前,永远不要关闭文件,以避免TOCTOU问题。 - anonymous

16

按照@shebaw所说,在UNIX操作系统中调用os.Stat更有效率,因为stat()是一种Unix系统调用,返回关于一个inode的文件属性,而不必打开文件处理。

注意: 使用其他方法可能会导致多线程/并发应用程序中出现太多打开的文件问题,因为您需要打开文件来查询统计信息

这里是基准测试结果

func GetFileSize1(filepath string) (int64, error) {
    fi, err := os.Stat(filepath)
    if err != nil {
        return 0, err
    }
    // get the size
    return fi.Size(), nil
}

func GetFileSize2(filepath string) (int64, error) {
    f, err := os.Open(filepath)
    if err != nil {
        return 0, err
    }
    defer f.Close()
    fi, err := f.Stat()
    if err != nil {
        return 0, err
    }
    return fi.Size(), nil
}
BenchmarkGetFileSize1-8           704618              1662 ns/op
BenchmarkGetFileSize2-8           199461              5668 ns/op

如果您需要保护免受TOCTOU问题的影响,绝对不应使用GetFileSize1()。对于任何不了解TOCTOU的人,请搜索一下,它们是由于在检查和使用之间发生变化而创建的安全问题。 - anonymous

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接