go os包文件操作詳解

1 os介紹

Go 在 os 中提供了文件的基本操作,包括通常意義的打開、創建、讀寫等操作,除此以外爲了追求便捷以及性能上,Go 還在 io/ioutil 以及 bufio 提供一些其他函數供開發者使用

2 練習

2.1 環境變量

2.1.1 獲取所有環境變量, 返回變量列表

func Environ() []string
package main
 
import (
    "fmt"
    "os"
    "strings"
)
 
func main() {
    envs := os.Environ()
    for _, env := range envs {
        cache := strings.Split(env, "=")
        fmt.Printf(`
        key: %s value: %s
        `, cache[0], cache[1])
    }
}
[root@localhost os]# go run os1.go

        key: XDG_SESSION_ID value: 27
        
        key: GUESTFISH_INIT value: \e[1;34m
        
        key: HOSTNAME value: localhost.localdomain
        ......

2.1.2 獲取指定環境變量

func Getenv(key string) string
package main
 
import (
    "fmt"
    "os"
)
 
func main() {
    fmt.Println(os.Getenv("GOPATH"))
}
[root@localhost os]#  go run os2.go
/usr/local/gopath

2.1.3 設置環境變量

func Setenv(key, value string) error
package main
 
import (
    "fmt"
    "os"
)
 
func main() {
    fmt.Println(os.Getenv("GOPATH"))
 
    if err := os.Setenv("GOPATH", "./GO/bin"); err != nil {
        fmt.Println(err)
    } else {
        fmt.Println("success")
    }
}
[root@localhost os]#  go run os3.go
/usr/local/gopath
success

2.1.4 清除所有環境變量

func os.Clearenv()
func main() {
 data := os.Environ() 
 fmt.Println(data)
 os.Clearenv() 
 data = os.Environ()
 fmt.Println(data) 
}

2.2 文件打開方式與打開模式(運用OpenFile函數)

//打開方式

const (
//只讀模式
O_RDONLY int = syscall.O_RDONLY // open the file read-only.
//只寫模式
O_WRONLY int = syscall.O_WRONLY // open the file write-only.
//可讀可寫
O_RDWR int = syscall.O_RDWR // open the file read-write.
//追加內容
O_APPEND int = syscall.O_APPEND // append data to the file when writing.
//創建文件,如果文件不存在
O_CREATE int = syscall.O_CREAT // create a new file if none exists.
//與創建文件一同使用,文件必須存在
O_EXCL int = syscall.O_EXCL // used with O_CREATE, file must not exist
//打開一個同步的文件流
O_SYNC int = syscall.O_SYNC // open for synchronous I/O.
//如果可能,打開時縮短文件
O_TRUNC int = syscall.O_TRUNC // if possible, truncate file when opened.
)

打開模式

const (
    // 單字符是被String方法用於格式化的屬性縮寫。
    ModeDir        FileMode = 1 << (32 - 1 - iota) // d: 目錄
    ModeAppend                                     // a: 只能寫入,且只能寫入到末尾
    ModeExclusive                                  // l: 用於執行
    ModeTemporary                                  // T: 臨時文件(非備份文件)
    ModeSymlink                                    // L: 符號鏈接(不是快捷方式文件)
    ModeDevice                                     // D: 設備
    ModeNamedPipe                                  // p: 命名管道(FIFO)
    ModeSocket                                     // S: Unix域socket
    ModeSetuid                                     // u: 表示文件具有其創建者用戶id權限
    ModeSetgid                                     // g: 表示文件具有其創建者組id的權限
    ModeCharDevice                                 // c: 字符設備,需已設置ModeDevice
    ModeSticky                                     // t: 只有root/創建者能刪除/移動文件
    // 覆蓋所有類型位(用於通過&獲取類型位),對普通文件,所有這些位都不應被設置
    ModeType = ModeDir | ModeSymlink | ModeNamedPipe | ModeSocket | ModeDevice
    ModePerm FileMode = 0777 // 覆蓋所有Unix權限位(用於通過&獲取類型位)
)

2.3 文件信息

type FileInfo interface {
    Name() string       // 文件的名字(不含擴展名)
    Size() int64        // 普通文件返回值表示其大小;其他文件的返回值含義各系統不同
    Mode() FileMode     // 文件的模式位
    ModTime() time.Time // 文件的修改時間
    IsDir() bool        // 等價於Mode().IsDir()
    Sys() interface{}   // 底層數據來源(可以返回nil)
}

2.3.1 獲取文件信息對象, 符號鏈接將跳轉

func Stat(name string) (fi FileInfo, err error)
package main
 
import (
    "fmt"
    "os"
)
 
func main() {
     fi, _ := os.Stat("./1.txt")
 
     fmt.Println(fi.Size())
}
[root@localhost os]# go run os4.go 
6

2.3.2 獲取文件信息對象, 符號鏈接不跳轉

package main

import (
“fmt”
“os”
)

func main() {
fi, _ := os.Lstat("./1.txt")

fmt.Println(fi.Size())

}
[root@localhost os]# go run os5.go
6

2.3.3 (重點)根據錯誤,判斷 文件或目錄是否存在

package main
 
import (
    "fmt"
    "os"
)
 
func main() {
    if _, err := os.Open("./empty.js"); err != nil {
        // false 不存在   true 存在
        emptyErr := os.IsExist(err)
        fmt.Println(emptyErr, "\n", err)
    }
}
[root@localhost os]#  go run os6.go
false 
 open ./empty.js: no such file or directory

2.3.4 IsExist 反義方法

package main
 
import (
    "fmt"
    "os"
)
 
func main() {
    if _, err := os.Open("./empty.js"); err != nil {
        // false 不存在   true 存在
        emptyErr := os.IsNotExist(err)
        fmt.Println(emptyErr, "\n", err)
    }
}
[root@localhost os]# go run os7.go
true 
 open ./empty.js: no such file or directory

2.3.5 根據錯誤,判斷是否爲權限錯誤

package main
 
import (
    "fmt"
    "os"
)
 
func main() {
    file, _ := os.Open("./cache.js")
    _, err := file.WriteString("// new info")
 
    if err != nil {
        fmt.Println(os.IsPermission(err))
    }
    defer file.Close()
}
[root@localhost os]#  go run os8.go
false

2.4 文件/目錄操作

屬性操作

2.4.1 (重點)獲取當前工作目錄

func Getwd() (dir string, err error)
package main
 
import (
    "fmt"
    "os"
)
 
func main() {
    path, _ := os.Getwd()
    fmt.Println(path)
}
[root@localhost os]# pwd
/root/go/os
[root@localhost os]#  go run  os9.go
/root/go/os

2.4.2 修改當前,工作目錄

func Chdir(dir string) error
package main
 
import (
    "fmt"
    "os"
)
 
func main() {
    path1, _ := os.Getwd()
    fmt.Println(path1)
    os.Chdir("./../")
    path, _ := os.Getwd()
    fmt.Println(path)
 
}
[root@localhost os]#  go run os10.go
/root/go/os
/root/go

2.4.3 修改文件的 FileMode

func Chmod(name string, mode FileMode) error

2.4.4 修改文件的 訪問時間和修改時間

func Chtimes(name string, atime time.Time, mtime time.Time) error
package main
 
import (
    "fmt"
    "os"
    "time"
)
 
func main() {
    fmt.Println(os.Getwd())
 
    path := "test.txt"
    os.Chtimes(path, time.Now(), time.Now())
 
    fi, _ := os.Stat(path)
    fmt.Println(fi.ModTime())
 
}
[root@localhost os]# go run os11.go
/root/go/os <nil>
2020-04-02 12:12:37.525936298 +0800 CST

下面是:增刪改查

2.4.5 (重點)創建目錄

func Mkdir(name string, perm FileMode) error
package main
 
import (
    "fmt"
    "os"
)
 
func main() {
    if err := os.Mkdir("test", os.ModeDir); err != nil {
        fmt.Println(err)
    } else {
        fmt.Println("success")
    }
 
}
[root@localhost os]# go run os12.go 
success
[root@localhost os]# go run os12.go 
mkdir test: file exists

2.4.6 遞歸創建目錄

func MkdirAll(path string, perm FileMode) error
package main
 
import (
    "fmt"
    "os"
)
 
func main() {
    if err := os.MkdirAll("test01/test", os.ModeDir); err != nil {
        fmt.Println(err)
    } else {
        fmt.Println("success")
    }
 
}
[root@localhost os]#  go run os13.go
success

2.4.7 移除文件或目錄(單一文件)

func Remove(name string) error
package main
import (
    "fmt"
    "os"
)
 
func main() {
    if err := os.Remove("test"); err != nil {
        fmt.Println(err)
    } else {
        fmt.Println("success")
    }
}
[root@localhost os]#  go run os14.go
success
[root@localhost os]# ls test
ls: 無法訪問test: 沒有那個文件或目錄
[root@localhost os]#  go run os14.go
remove test: no such file or directory

2.4.8 遞歸刪除文件或目錄

func RemoveAll(path string) error
package main
 
import (
    "fmt"
    "os"
)
 
func main() {
    if err := os.RemoveAll("test01"); err != nil {
        fmt.Println(err)
    } else {
        fmt.Println("success")
    }
} 
[root@localhost os]#  go run os15.go
success

2.4.8 文件重名或移動

func Rename(oldpath, newpath string) error
package main
 
import (
    "fmt"
    "os"
)
 
func main() {
 
    // 重命名
    err := os.Rename("test.txt", "test01.js")
    if err != nil {
        fmt.Println(err)
    }
    err = os.Mkdir("test", os.ModeDir)
    if err != nil {
        fmt.Println(err)
    }
 
    // 移動
    err = os.Rename("test01.js", "test/text01.txt")
    if err != nil {
        fmt.Println(err)
    }
}
[root@localhost os]#  go run os16.go
[root@localhost os]#  go run os16.go
rename test.txt test01.js: no such file or directory
mkdir test: file exists
rename test01.js test/text01.txt: no such file or directory
[root@localhost os]# ls test/
text01.txt

2.4.9 修改文件大小

func Truncate(name string, size int64) error
package main
 
import (
    "fmt"
    "os"
)
 
func main() {
 
    path := "test/text01.txt"
    fi, err := os.Stat(path)
    if err != nil {
        fmt.Println(err)
        os.Exit(1)
    }
 
    size := fi.Size()
    fmt.Println(size)
 
    // 截取長度
    size = int64(float64(size) * 0.5)
 
    os.Truncate(path, size)
 
    fi, _ = os.Stat(path)
 
    fmt.Println(fi.Size())
}
[root@localhost os]# cat test/text01.txt
abc
123
[root@localhost os]# go run os17.go
&{text01.txt 8 420 {99442120 63721429367 0x570b80} {64768 3725573 1 33188 0 0 0 0 8 4096 8 {1585832567 99442120} {1585832567 99442120} {1585832567 101442065} [0 0 0]}}
8
4
[root@localhost os]# cat test/text01.txt   #123被刪除
abc

2.4.10 比較兩個文件信息對象,是否指向同一文件

func SameFile(fi1, fi2 FileInfo) bool
package main
 
import (
    "fmt"
    "os"
)
 
func main() {
 
    path := "test/text01.txt"
 
    fi_1, _ := os.Stat(path)
    fi_2, _ := os.Stat(path)
 
    fmt.Println(os.SameFile(fi_1, fi_2))
}
[root@localhost os]# vim os18.go^C
[root@localhost os]# go run os18.go 
true

2.5 文件/目錄對象

2.5.1 (重點)創建文件, 如果文件存在,清空原文件

func Create(name string) (file *File, err error)
package main
import (
    "fmt"
    "os"
)
 
func main() {
 
    file, _ := os.Create("./new_file.js")
    fmt.Println(file.Name())
}
[root@localhost os]# go run os19.go
./new_file.js
[root@localhost os]# ls new_file.js 
new_file.js

2.5.2 打開文件,獲取文件對象, 以讀取模式打開

Open打開一個文件用於讀取。如果操作成功,返回的文件對象的方法可用於讀取數據;對應的文件描述符具有O_RDONLY模式。如果出錯,錯誤底層類型是*PathError。
所以,Open()只能用於讀取文件。

func Open(name string) (file *File, err error)
package main
 
import (
    "fmt"
    "os"
)
 
func main() {
 
    file, _ := os.Open("./new_file.js")
    fmt.Println(file.Name())
}
[root@localhost os]# go run os20.go
./new_file.js
[root@localhost os]# rm -rf new_file.js 
[root@localhost os]# go run os20.go
panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x0 pc=0x48d6f0]

goroutine 1 [running]:
os.(*File).Name(...)
	/usr/local/go/src/os/file.go:54
main.main()
	/root/go/os/os20.go:11 +0x50
exit status 2

2.5.3 (重點)以指定模式,打開文件

func OpenFile(name string, flag int, perm FileMode) (file *File, err error)
package main
 
import (
    "fmt"
    "os"
)
 
func main() {
 
    file, _ := os.OpenFile("./new_file.js", os.O_RDONLY, os.ModeAppend)
    fmt.Println(file.Name())
}
[root@localhost os]# cat new_file.js 
[root@localhost os]# go run os21.go
./new_file.js

2.6 文件對象屬性操縱

2.6.1 獲取文件路徑

Name

func (f *File) Name() string

2.6.2 獲取文件信息對象

Stat

func (f *File) Stat() (fi FileInfo, err error)

2.6.3 將當前工作路徑修改爲文件對象目錄, 文件對象必須爲目錄, 該接口不支持window

Chdir

func (f *File) Chdir() error

2.6.4 修改文件模式

Chmod

func (f *File) Chmod(mode FileMode) error

Truncate

2.6.5 修改文件對象size

func (f *File) Truncate(size int64) error

2.7 文件對象讀寫操作

2.7.1 讀取文件內容, 讀入長度取決 容器切片長度

Read

func (f *File) Read(b []byte) (n int, err error)
package main
 
import (
    "fmt"
    "os"
)
 
func main() {
 
    bt := make([]byte, 10)
    file, _ := os.Open("./new_file.js")
 
    file.Read(bt)
    defer file.Close()
 
    fmt.Println(string(bt))
}
[root@localhost os]# cat new_file.js 
12345679890
nihao,my name is ghostwritten
[root@localhost os]# go run os22.go
1234567989

2.7.2 從某位置,讀取文件內容

ReadAt

func (f *File) ReadAt(b []byte, off int64) (n int, err error)
package main
 
import (
    "fmt"
    "os"
)
 
func main() {
 
    bt := make([]byte, 100)
    file, _ := os.Open("test/text01.txt")
 
    file.ReadAt(bt, 2)
 
    fmt.Println(string(bt))
}
[root@localhost os]# cat test/text01.txt 
abcdefgh
[root@localhost os]#  go run os23.go
cdefgh

2.7.3 (重點)寫入內容

Write

func (f *File) Write(b []byte) (n int, err error)
package main
 
import (
    "fmt"
    "os"
)
 
func main() {
 
    file, err := os.OpenFile("test/text01.txt", os.O_RDWR, os.ModeAppend)
    if err != nil {
        fmt.Println("err: ", err)
        os.Exit(1)
    }
 
    defer file.Close()
 
    if n, err := file.Write([]byte("// new info")); err != nil {
        fmt.Println(err)
    } else {
        fmt.Println(n)
    }
 
}
[root@localhost os]# go run os24.go
11
[root@localhost os]# cat test/text01.txt 
// new info

2.7.4 寫入字符

WriteString

func (f *File) WriteString(s string) (ret int, err error)
package main
 
import (
    "fmt"
    "os"
)
 
func main() {
 
    file, err := os.OpenFile("test/text01.txt", os.O_RDWR, os.ModeAppend)
    if err != nil {
        fmt.Println("err: ", err)
        os.Exit(1)
    }
 
    defer file.Close()
 
    if n, err := file.Write([]byte("// new info")); err != nil {
        fmt.Println(err)
    } else {
        fmt.Println(n)
    }
 
}
[root@localhost os]# go run os25.go
12
[root@localhost os]# cat test/text01.txt 
// test info

2.7.5 從指定位置,寫入

WriteAt

func (f *File) WriteAt(b []byte, off int64) (n int, err error)
package main
 
import (
    "fmt"
    "os"
)
 
func main() {
 
    file, err := os.OpenFile("test/text01.txt", os.O_RDWR, os.ModeAppend)
    if err != nil {
        fmt.Println("err: ", err)
        os.Exit(1)
    }
 
    defer file.Close()
 
    if n, err := file.WriteAt([]byte(" append "), 5); err != nil {
        fmt.Println(err)
    } else {
        fmt.Println(n)
    }
 
}
[root@localhost os]# go run os26.go
8
[root@localhost os]# cat test/text01.txt 
// te append 

2.7.6 設置下次讀寫位置

Seek

func (f *File) Seek(offset int64, whence int) (ret int64, err error)
package main
 
import (
    "fmt"
    "os"
)
 
func main() {
 
    f, err := os.OpenFile("test/text01.txt", os.O_RDWR, os.ModeAppend)
    if err != nil {
        fmt.Println("err: ", err)
        os.Exit(1)
    }
 
    defer f.Close()
 
    f.Seek(2, 0)
    buffer := make([]byte, 5)
    // Read 後文件指針也會偏移
 
    n, err := f.Read(buffer)
    if err != nil {
        fmt.Println(nil)
        return
    }
    fmt.Printf("n is %d, buffer content is : %s\n", n, buffer)
    // 獲取文件指針當前位置
    cur_offset, _ := f.Seek(0, os.SEEK_CUR)
    fmt.Printf("current offset is %d\n", cur_offset)
 
}
[root@localhost os]# go run os27.go
n is 5, buffer content is : 34567
current offset is 7
[root@localhost os]# cat test/text01.txt 
1234567890abcdefg

參考連接:
https://www.cnblogs.com/saryli/p/11691142.html

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章