Go官方库的文件操作分散在多个包中,比如os
、ioutil
包,发现已经有人2015年已经写了一篇这样的文章,写的非常好,我经常在需要使用文件方法的时候回过来查,所以翻译成了中文,记录一下. 原文 Working with Files in Go , 作者 NanoDano
介绍 万物皆文件 UNIX 的一个基础设计就是”万物皆文件”(everything is a file)。我们不必知道一个文件到底映射成什么,操作系统的设备驱动抽象成文件。操作系统为设备提供了文件格式的接口 Go语言中的reader和writer接口也类似。我们只需简单的读写字节,不必知道reader的数据来自哪里,也不必知道writer将数据发送到哪里。 你可以在/dev
下查看可用的设备,有些可能需要较高的权限才能访问。
基本操作
创建空文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 package mainimport ( "log" "os" ) var ( newFile *os.File err error ) func main () { newFile, err = os.Create("test.txt" ) if err != nil { log.Fatal(err) } log.Println(newFile) newFile.Close() }
Truncate文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 package mainimport ( "log" "os" ) func main () { err := os.Truncate("test.txt" , 100 ) if err != nil { log.Fatal(err) } }
得到文件信息
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 package mainimport ( "fmt" "log" "os" ) var ( fileInfo os.FileInfo err error ) func main () { fileInfo, err = os.Stat("test.txt" ) if err != nil { log.Fatal(err) } fmt.Println("File name:" , fileInfo.Name()) fmt.Println("Size in bytes:" , fileInfo.Size()) fmt.Println("Permissions:" , fileInfo.Mode()) fmt.Println("Last modified:" , fileInfo.ModTime()) fmt.Println("Is Directory: " , fileInfo.IsDir()) fmt.Printf("System interface type: %T\n" , fileInfo.Sys()) fmt.Printf("System info: %+v\n\n" , fileInfo.Sys()) }
重命名和移动
1 2 3 4 5 6 7 8 9 10 11 12 13 package mainimport ( "log" "os" ) func main () { originalPath := "test.txt" newPath := "test2.txt" err := os.Rename(originalPath, newPath) if err != nil { log.Fatal(err) } }
删除文件
1 2 3 4 5 6 7 8 9 10 11 package mainimport ( "log" "os" ) func main () { err := os.Remove("test.txt" ) if err != nil { log.Fatal(err) } }
打开和关闭文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 package mainimport ( "log" "os" ) func main () { file, err := os.Open("test.txt" ) if err != nil { log.Fatal(err) } file.Close() file, err = os.OpenFile("test.txt" , os.O_APPEND, 0666 ) if err != nil { log.Fatal(err) } file.Close() }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 package mainimport ( "log" "os" ) var ( fileInfo *os.FileInfo err error ) func main () { fileInfo, err := os.Stat("test.txt" ) if err != nil { if os.IsNotExist(err) { log.Fatal("File does not exist." ) } } log.Println("File does exist. File information:" ) log.Println(fileInfo) }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 package mainimport ( "log" "os" ) func main () { file, err := os.OpenFile("test.txt" , os.O_WRONLY, 0666 ) if err != nil { if os.IsPermission(err) { log.Println("Error: Write permission denied." ) } } file.Close() file, err = os.OpenFile("test.txt" , os.O_RDONLY, 0666 ) if err != nil { if os.IsPermission(err) { log.Println("Error: Read permission denied." ) } } file.Close() }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 package mainimport ( "log" "os" "time" ) func main () { err := os.Chmod("test.txt" , 0777 ) if err != nil { log.Println(err) } err = os.Chown("test.txt" , os.Getuid(), os.Getgid()) if err != nil { log.Println(err) } twoDaysFromNow := time.Now().Add(48 * time.Hour) lastAccessTime := twoDaysFromNow lastModifyTime := twoDaysFromNow err = os.Chtimes("test.txt" , lastAccessTime, lastModifyTime) if err != nil { log.Println(err) } }
一个普通的文件是一个指向硬盘的inode的地方。 硬链接创建一个新的指针指向同一个地方。只有所有的链接被删除后文件才会被删除。硬链接只在相同的文件系统中才工作。你可以认为一个硬链接是一个正常的链接。
symbolic link,又叫软连接,和硬链接有点不一样,它不直接指向硬盘中的相同的地方,而是通过名字引用其它文件。他们可以指向不同的文件系统中的不同文件。并不是所有的操作系统都支持软链接。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 package mainimport ( "os" "log" "fmt" ) func main () { err := os.Link("original.txt" , "original_also.txt" ) if err != nil { log.Fatal(err) } fmt.Println("creating sym" ) err = os.Symlink("original.txt" , "original_sym.txt" ) if err != nil { log.Fatal(err) } fileInfo, err := os.Lstat("original_sym.txt" ) if err != nil { log.Fatal(err) } fmt.Printf("Link info: %+v" , fileInfo) err = os.Lchown("original_sym.txt" , os.Getuid(), os.Getgid()) if err != nil { log.Fatal(err) } }