文件信息操作 #
在实际开发中,经常需要获取文件的各种信息,如文件大小、修改时间、权限等。Go语言的 os 包提供了丰富的文件信息操作功能。
获取文件信息 #
使用 os.Stat #
os.Stat 返回文件的详细信息:
go
package main
import (
"fmt"
"os"
"time"
)
func main() {
fileInfo, err := os.Stat("example.txt")
if err != nil {
if os.IsNotExist(err) {
fmt.Println("文件不存在")
} else {
fmt.Println("获取信息失败:", err)
}
return
}
fmt.Println("文件名:", fileInfo.Name())
fmt.Println("文件大小:", fileInfo.Size(), "字节")
fmt.Println("修改时间:", fileInfo.ModTime().Format(time.RFC3339))
fmt.Println("是否为目录:", fileInfo.IsDir())
fmt.Println("文件权限:", fileInfo.Mode())
}
FileInfo 接口 #
FileInfo 是一个接口,包含以下方法:
go
type FileInfo interface {
Name() string // 文件名
Size() int64 // 文件大小(字节)
Mode() FileMode // 文件模式(权限)
ModTime() time.Time // 修改时间
IsDir() bool // 是否为目录
Sys() any // 底层数据源
}
检查文件是否存在 #
推荐方式 #
go
package main
import (
"fmt"
"os"
)
func fileExists(filename string) bool {
_, err := os.Stat(filename)
return !os.IsNotExist(err)
}
func main() {
if fileExists("example.txt") {
fmt.Println("文件存在")
} else {
fmt.Println("文件不存在")
}
}
详细检查 #
go
package main
import (
"fmt"
"os"
)
func checkFile(filename string) {
info, err := os.Stat(filename)
if err != nil {
if os.IsNotExist(err) {
fmt.Println("文件不存在")
} else if os.IsPermission(err) {
fmt.Println("权限不足")
} else {
fmt.Println("其他错误:", err)
}
return
}
if info.IsDir() {
fmt.Println("这是一个目录")
} else {
fmt.Println("这是一个文件")
}
}
func main() {
checkFile("example.txt")
checkFile("nonexistent.txt")
}
文件权限操作 #
FileMode 类型 #
FileMode 表示文件模式和权限:
go
package main
import (
"fmt"
"os"
)
func main() {
info, _ := os.Stat("example.txt")
mode := info.Mode()
fmt.Println("权限字符串:", mode.String())
fmt.Println("权限数值:", uint32(mode))
if mode&os.ModeDir != 0 {
fmt.Println("是目录")
}
if mode&0400 != 0 {
fmt.Println("所有者可读")
}
if mode&0200 != 0 {
fmt.Println("所有者可写")
}
if mode&0100 != 0 {
fmt.Println("所有者可执行")
}
}
修改文件权限 #
go
package main
import (
"fmt"
"os"
)
func main() {
err := os.Chmod("example.txt", 0644)
if err != nil {
fmt.Println("修改权限失败:", err)
return
}
info, _ := os.Stat("example.txt")
fmt.Println("新权限:", info.Mode())
}
常用权限值:
| 权限 | 数值 | 说明 |
|---|---|---|
| 0777 | 所有权限 | 所有人可读写执行 |
| 0755 | 标准目录权限 | 所有者全权限,其他人可读可执行 |
| 0644 | 标准文件权限 | 所有者可读写,其他人只读 |
| 0600 | 私有文件 | 只有所有者可读写 |
修改文件时间戳 #
go
package main
import (
"fmt"
"os"
"time"
)
func main() {
accessTime := time.Now()
modifyTime := time.Now()
err := os.Chtimes("example.txt", accessTime, modifyTime)
if err != nil {
fmt.Println("修改时间失败:", err)
return
}
info, _ := os.Stat("example.txt")
fmt.Println("新的修改时间:", info.ModTime())
}
符号链接操作 #
使用 Lstat 获取链接信息 #
Lstat 与 Stat 的区别在于,当文件是符号链接时,Lstat 返回链接本身的信息:
go
package main
import (
"fmt"
"os"
)
func main() {
linkInfo, err := os.Lstat("symlink")
if err != nil {
fmt.Println("获取链接信息失败:", err)
return
}
if linkInfo.Mode()&os.ModeSymlink != 0 {
fmt.Println("这是一个符号链接")
target, err := os.Readlink("symlink")
if err != nil {
fmt.Println("读取链接目标失败:", err)
return
}
fmt.Println("链接目标:", target)
}
}
创建符号链接 #
go
package main
import (
"fmt"
"os"
)
func main() {
err := os.Symlink("original.txt", "link_to_original")
if err != nil {
fmt.Println("创建链接失败:", err)
return
}
fmt.Println("符号链接创建成功")
}
创建硬链接 #
go
package main
import (
"fmt"
"os"
)
func main() {
err := os.Link("original.txt", "hardlink_to_original")
if err != nil {
fmt.Println("创建硬链接失败:", err)
return
}
fmt.Println("硬链接创建成功")
}
文件大小格式化 #
go
package main
import (
"fmt"
"os"
)
func formatSize(bytes int64) string {
const (
KB = 1024
MB = KB * 1024
GB = MB * 1024
)
switch {
case bytes >= GB:
return fmt.Sprintf("%.2f GB", float64(bytes)/float64(GB))
case bytes >= MB:
return fmt.Sprintf("%.2f MB", float64(bytes)/float64(MB))
case bytes >= KB:
return fmt.Sprintf("%.2f KB", float64(bytes)/float64(KB))
default:
return fmt.Sprintf("%d B", bytes)
}
}
func main() {
info, err := os.Stat("example.txt")
if err != nil {
fmt.Println("错误:", err)
return
}
fmt.Printf("文件大小: %s\n", formatSize(info.Size()))
}
实用示例:文件信息报告 #
go
package main
import (
"fmt"
"os"
"time"
)
func printFileInfo(filename string) {
info, err := os.Stat(filename)
if err != nil {
fmt.Printf("无法获取 %s 的信息: %v\n", filename, err)
return
}
fmt.Println("========== 文件信息报告 ==========")
fmt.Printf("文件名: %s\n", info.Name())
fmt.Printf("大小: %d 字节\n", info.Size())
fmt.Printf("修改时间: %s\n", info.ModTime().Format("2006-01-02 15:04:05"))
fmt.Printf("权限: %s\n", info.Mode())
mode := info.Mode()
if mode.IsDir() {
fmt.Println("类型: 目录")
} else if mode&os.ModeSymlink != 0 {
fmt.Println("类型: 符号链接")
} else {
fmt.Println("类型: 普通文件")
}
fmt.Printf("权限详情: ")
printPermissions(mode)
fmt.Println()
}
func printPermissions(mode os.FileMode) {
perms := []struct {
bit os.FileMode
char string
}{
{0400, "r"}, {0200, "w"}, {0100, "x"},
{0040, "r"}, {0020, "w"}, {0010, "x"},
{0004, "r"}, {0002, "w"}, {0001, "x"},
}
for _, p := range perms {
if mode&p.bit != 0 {
fmt.Print(p.char)
} else {
fmt.Print("-")
}
}
}
func main() {
if len(os.Args) < 2 {
fmt.Println("用法: go run main.go <文件名>")
return
}
printFileInfo(os.Args[1])
}
小结 #
| 函数 | 用途 |
|---|---|
os.Stat |
获取文件信息(跟随符号链接) |
os.Lstat |
获取文件信息(不跟随符号链接) |
os.IsNotExist |
检查是否为"文件不存在"错误 |
os.IsPermission |
检查是否为"权限不足"错误 |
os.Chmod |
修改文件权限 |
os.Chtimes |
修改文件时间戳 |
os.Symlink |
创建符号链接 |
os.Link |
创建硬链接 |
os.Readlink |
读取符号链接目标 |
掌握文件信息操作是进行高级文件处理的基础,在实际开发中经常用于文件验证、权限检查等场景。