Go语言常用文件操作汇总
一切都是文件
UNIX的基本方面之一是
一切都是文件
。我们不一定知道文件描述符所映射的内容,这是由操作系统的设备驱动程序抽象的。操作系统以文件形式为我们提供了到设备的接口。
Go中的读取器和写入器接口是相似的抽象。我们只需读取和写入字节,而无需了解读取器从何处或如何获取数据或写入器在何处发送数据。 在/dev中查找可用的设备。 有些将需要提升的特权才能访问。
创建空文件
1package main
2
3import (
4 "log"
5 "os"
6)
7
8var (
9 newFile *os.File
10 err error
11)
12
13func main() {
14 newFile, err = os.Create("test.txt")
15 if err != nil {
16 log.Fatal(err)
17 }
18 log.Println(newFile)
19 newFile.Close()
20}
截取文件
1package main
2
3import (
4 "log"
5 "os"
6)
7
8func main() {
9 // Truncate a file to 100 bytes. If file
10 // is less than 100 bytes the original contents will remain
11 // at the beginning, and the rest of the space is
12 // filled will null bytes. If it is over 100 bytes,
13 // Everything past 100 bytes will be lost. Either way
14 // we will end up with exactly 100 bytes.
15 // Pass in 0 to truncate to a completely empty file
16
17 err := os.Truncate("test.txt", 100)
18 if err != nil {
19 log.Fatal(err)
20 }
21}
获取文件信息
1package main
2
3import (
4 "fmt"
5 "log"
6 "os"
7)
8
9var (
10 fileInfo os.FileInfo
11 err error
12)
13
14func main() {
15 // Stat returns file info. It will return
16 // an error if there is no file.
17 fileInfo, err = os.Stat("test.txt")
18 if err != nil {
19 log.Fatal(err)
20 }
21 fmt.Println("File name:", fileInfo.Name())
22 fmt.Println("Size in bytes:", fileInfo.Size())
23 fmt.Println("Permissions:", fileInfo.Mode())
24 fmt.Println("Last modified:", fileInfo.ModTime())
25 fmt.Println("Is Directory: ", fileInfo.IsDir())
26 fmt.Printf("System interface type: %T\n", fileInfo.Sys())
27 fmt.Printf("System info: %+v\n\n", fileInfo.Sys())
28}
重命名或移动文件
1package main
2
3import (
4 "log"
5 "os"
6)
7
8func main() {
9 originalPath := "test.txt"
10 newPath := "test2.txt"
11 err := os.Rename(originalPath, newPath)
12 if err != nil {
13 log.Fatal(err)
14 }
15}
删除文件
1package main
2
3import (
4 "log"
5 "os"
6)
7
8func main() {
9 err := os.Remove("test.txt")
10 if err != nil {
11 log.Fatal(err)
12 }
13}
打开或关闭文件
1package main
2
3import (
4 "log"
5 "os"
6)
7
8func main() {
9 // Simple read only open. We will cover actually reading
10 // and writing to files in examples further down the page
11 file, err := os.Open("test.txt")
12 if err != nil {
13 log.Fatal(err)
14 }
15 file.Close()
16
17 // OpenFile with more options. Last param is the permission mode
18 // Second param is the attributes when opening
19 file, err = os.OpenFile("test.txt", os.O_APPEND, 0666)
20 if err != nil {
21 log.Fatal(err)
22 }
23 file.Close()
24
25 // Use these attributes individually or combined
26 // with an OR for second arg of OpenFile()
27 // e.g. os.O_CREATE|os.O_APPEND
28 // or os.O_CREATE|os.O_TRUNC|os.O_WRONLY
29
30 // os.O_RDONLY // Read only
31 // os.O_WRONLY // Write only
32 // os.O_RDWR // Read and write
33 // os.O_APPEND // Append to end of file 附加到文件末尾
34 // os.O_CREATE // Create is none exist
35 // os.O_TRUNC // Truncate file when opening 打开时截断文件
36}
检查文件是否存在
1package main
2
3import (
4 "log"
5 "os"
6)
7
8var (
9 fileInfo *os.FileInfo
10 err error
11)
12
13func main() {
14 // Stat returns file info. It will return
15 // an error if there is no file.
16 fileInfo, err := os.Stat("test.txt")
17 if err != nil {
18 if os.IsNotExist(err) {
19 log.Fatal("File does not exist.")
20 }
21 }
22 log.Println("File does exist. File information:")
23 log.Println(fileInfo)
24}
检查读取和写入权限
1package main
2
3import (
4 "log"
5 "os"
6)
7
8func main() {
9 // Test write permissions. It is possible the file
10 // does not exist and that will return a different
11 // error that can be checked with os.IsNotExist(err)
12 file, err := os.OpenFile("test.txt", os.O_WRONLY, 0666)
13 if err != nil {
14 if os.IsPermission(err) {
15 log.Println("Error: Write permission denied.")
16 }
17 }
18 file.Close()
19
20 // Test read permissions
21 file, err = os.OpenFile("test.txt", os.O_RDONLY, 0666)
22 if err != nil {
23 if os.IsPermission(err) {
24 log.Println("Error: Read permission denied.")
25 }
26 }
27 file.Close()
28}
更改权限,所有权和时间戳
1package main
2
3import (
4 "log"
5 "os"
6 "time"
7)
8
9func main() {
10 // Change perrmissions using Linux style
11 err := os.Chmod("test.txt", 0777)
12 if err != nil {
13 log.Println(err)
14 }
15
16 // Change ownership
17 err = os.Chown("test.txt", os.Getuid(), os.Getgid())
18 if err != nil {
19 log.Println(err)
20 }
21
22 // Change timestamps
23 twoDaysFromNow := time.Now().Add(48 * time.Hour)
24 lastAccessTime := twoDaysFromNow
25 lastModifyTime := twoDaysFromNow
26 err = os.Chtimes("test.txt", lastAccessTime, lastModifyTime)
27 if err != nil {
28 log.Println(err)
29 }
30}
硬链接和符号链接
典型的文件只是指向硬盘上称为inode的位置的指针。 硬链接会创建指向同一位置的新指针。 删除所有链接后,才会从磁盘上删除文件。 硬链接仅适用于同一文件系统。 硬链接是您可能认为的“正常”链接。
符号链接或软链接略有不同,它并不直接指向磁盘上的某个位置。 符号链接仅按名称引用其他文件。 它们可以指向不同文件系统上的文件。 并非所有系统都支持符号链接。
1package main
2
3import (
4 "os"
5 "log"
6 "fmt"
7)
8
9func main() {
10 // Create a hard link 硬链接
11 // You will have two file names that point to the same contents
12 // Changing the contents of one will change the other
13 // Deleting/renaming one will not affect the other
14 err := os.Link("original.txt", "original_also.txt")
15 if err != nil {
16 log.Fatal(err)
17 }
18
19 fmt.Println("creating sym")
20 // Create a symlink 符号链接
21 err = os.Symlink("original.txt", "original_sym.txt")
22 if err != nil {
23 log.Fatal(err)
24 }
25
26 // Lstat will return file info, but if it is actually
27 // a symlink, it will return info about the symlink.
28 // It will not follow the link and give information
29 // about the real file
30 // Symlinks do not work in Windows
31 fileInfo, err := os.Lstat("original_sym.txt")
32 if err != nil {
33 log.Fatal(err)
34 }
35 fmt.Printf("Link info: %+v", fileInfo)
36
37 // Change ownership of a symlink only
38 // and not the file it points to
39 err = os.Lchown("original_sym.txt", os.Getuid(), os.Getgid())
40 if err != nil {
41 log.Fatal(err)
42 }
43}
复制文件
1package main
2
3import (
4 "os"
5 "log"
6 "io"
7)
8
9// Copy a file
10func main() {
11 // Open original file
12 originalFile, err := os.Open("test.txt")
13 if err != nil {
14 log.Fatal(err)
15 }
16 defer originalFile.Close()
17
18 // Create new file
19 newFile, err := os.Create("test_copy.txt")
20 if err != nil {
21 log.Fatal(err)
22 }
23 defer newFile.Close()
24
25 // Copy the bytes to destination from source
26 bytesWritten, err := io.Copy(newFile, originalFile)
27 if err != nil {
28 log.Fatal(err)
29 }
30 log.Printf("Copied %d bytes.", bytesWritten)
31
32 // Commit the file contents
33 // Flushes memory to disk
34 err = newFile.Sync()
35 if err != nil {
36 log.Fatal(err)
37 }
38}
在文件中寻找位置
1package main
2
3import (
4 "os"
5 "fmt"
6 "log"
7)
8
9func main() {
10 file, _ := os.Open("test.txt")
11 defer file.Close()
12
13 // Offset is how many bytes to move
14 // Offset can be positive or negative
15 var offset int64 = 5
16
17 // Whence is the point of reference for offset
18 // 0 = Beginning of file
19 // 1 = Current position
20 // 2 = End of file
21 var whence int = 0
22 newPosition, err := file.Seek(offset, whence)
23 if err != nil {
24 log.Fatal(err)
25 }
26 fmt.Println("Just moved to 5:", newPosition)
27
28 // Go back 2 bytes from current position
29 newPosition, err = file.Seek(-2, 1)
30 if err != nil {
31 log.Fatal(err)
32 }
33 fmt.Println("Just moved back two:", newPosition)
34
35 // Find the current position by getting the
36 // return value from Seek after moving 0 bytes
37 currentPosition, err := file.Seek(0, 1)
38 fmt.Println("Current position:", currentPosition)
39
40 // Go to beginning of file
41 newPosition, err = file.Seek(0, 0)
42 if err != nil {
43 log.Fatal(err)
44 }
45 fmt.Println("Position after seeking 0,0:", newPosition)
46}
将字节写入文件
您可以只使用打开文件所需的os包进行编写。 由于所有Go可执行文件都是静态链接的二进制文件,因此导入的每个程序包都会增加可执行文件的大小。 诸如io,ioutil和bufio之类的其他软件包提供了更多帮助,但不是必需的。
1package main
2
3import (
4 "os"
5 "log"
6)
7
8func main() {
9 // Open a new file for writing only
10 file, err := os.OpenFile(
11 "test.txt",
12 os.O_WRONLY|os.O_TRUNC|os.O_CREATE,
13 0666,
14 )
15 if err != nil {
16 log.Fatal(err)
17 }
18 defer file.Close()
19
20 // Write bytes to file
21 byteSlice := []byte("Bytes!\n")
22 bytesWritten, err := file.Write(byteSlice)
23 if err != nil {
24 log.Fatal(err)
25 }
26 log.Printf("Wrote %d bytes.\n", bytesWritten)
27}
快速写入文件
ioutil包有一个名为WriteFile()的有用函数,它将处理创建/打开、写入一个字节片段和关闭。如果您只需要一种快速的方法将一段字节转储到一个文件中,那么它非常有用。
1package main
2
3import (
4 "io/ioutil"
5 "log"
6)
7
8func main() {
9 err := ioutil.WriteFile("test.txt", []byte("Hi\n"), 0666)
10 if err != nil {
11 log.Fatal(err)
12 }
13}