读文件
要点
- 打开文件:file, err := os.Open(filename)
- 关闭文件:file.Close()
- 确定文件大小:stat, err := file.Stat()
- 准备存储空间:bs := make([]byte, stat.Size())
- 读文件:file.Read(bs)
示例
package main
import "fmt"
import "os"
// Read the text file's content.
// Copied from <<Introducing Go>> Page 68
func ReadFile(fileName string) (content string, ok bool) {
file, err := os.Open(fileName)
if err != nil {
ok = false
return
}
defer file.Close()
// get the file size
stat, err := file.Stat()
if err != nil {
ok = false
return
}
// read the file
bs := make([]byte, stat.Size())
_, err = file.Read(bs)
if err != nil {
ok = false
return
}
content = string(bs)
ok = true
return
}
func main() {
content, ok := ReadFile("helloworld.go")
if ok {
fmt.Println(content)
} else {
fmt.Println("Something error!")
}
}
轻量级读文件
要点:
- ioutil.ReadFile(filename)
Go的库对读文件做了封装,如下。
package main
import "fmt"
import "io/ioutil"
func main() {
content, err := ioutil.ReadFile("helloworld.go")
if err == nil {
fmt.Println(string(content))
} else {
fmt.Println("Something error!")
}
}
写文件
要点
- file, err := os.Create(fileName)
- file.WriteString(content)
代码
package main
import "fmt"
import "os"
// Create a file, and writen content to this file.
func WriteFile(fileName, content string) (ok bool) {
file, err := os.Create(fileName)
if err != nil {
ok = false
return
}
defer file.Close()
file.WriteString(content)
ok = true
return
}
func main() {
ok := WriteFile("test.txt", "some content")
if ok {
fmt.Println("ok")
} else {
fmt.Println("failed")
}
}
读目录
package main
import "fmt"
import "os"
func main() {
dir, err := os.Open(".")
if err != nil {
return
}
defer dir.Close()
fileinfos, err := dir.Readdir(-1)
if err != nil {
return
}
for _, fi := range fileinfos {
fmt.Println(fi.Name())
}
}
递归遍历目录
遍历某个目录是常用的一项需求。
代码
package main
import (
"fmt"
"os"
"path/filepath"
)
func main() {
filepath.Walk(".", func(path string, info os.FileInfo, err error) error {
fmt.Println(path)
return nil
})
}
运行结果(示例):
D:\examples>go run helloworld.go
.
helloworld.exe
helloworld.go
math.txt
test.txt
the_go_path
the_go_path\pkg
the_go_path\pkg\windows_amd64
the_go_path\pkg\windows_amd64\mymath.a
the_go_path\pkg\windows_amd64\shape.a
the_go_path\pkg\windows_amd64\shape2.a
the_go_path\src
the_go_path\src\mymath
the_go_path\src\mymath\mymath.go
the_go_path\src\mymath\mymath_test.go
the_go_path\src\shape
the_go_path\src\shape\the_shape.go
the_go_path\src\shape2
the_go_path\src\shape2\the_shape.go
the_shape.go
D:\examples>
Walk()
D:\examples>godoc path/filepath Walk
use 'godoc cmd/path/filepath' for documentation on the path/filepath command
func Walk(root string, walkFn WalkFunc) error
Walk walks the file tree rooted at root, calling walkFn for each file or
directory in the tree, including root. All errors that arise visiting
files and directories are filtered by walkFn. The files are walked in
lexical order, which makes the output deterministic but means that for
very large directories Walk can be inefficient. Walk does not follow
symbolic links.
丰富自己的Utilities
接下来基于上面的示例代码,写一个获取指定目录(包括子目录)下文件列表的函数:
package main
import (
"fmt"
"os"
"path/filepath"
)
func GetAllFiles(path string) (files []string, ok bool) {
the_files := []string {}
ok = true
filepath.Walk(path, func(path string, info os.FileInfo, err error) error {
if err != nil {
fmt.Println(err)
ok = false
} else {
the_files = append(the_files, path)
}
return nil
})
if ok {
files = the_files[:]
}
return
}
func main() {
files, ok := GetAllFiles(".") // or "./abcdefgxyz" to see the error.
if ok {
fmt.Println("All files:")
for _, file := range files {
fmt.Println(file)
}
} else {
fmt.Println("Get files failed.")
}
}
只获取当前目录下的文件列表
package main
import "fmt"
//import "os"
import "io/ioutil"
func GetCurDirFiles(path string) []string {
fileInfos, err := ioutil.ReadDir(path)
if err != nil {
fmt.Println(err)
return nil
}
files := []string{}
for _, fi := range fileInfos {
if !fi.IsDir() {
files = append(files, fi.Name())
}
}
return files
}
func main() {
files := GetCurDirFiles(".")
for _, file := range files {
fmt.Println(file)
}
}