package main
import (
"bufio"
"fmt"
"io"
"io/ioutil"
"log"
"os"
)
//文件目錄樹形結構節點
type dirTreeNode struct {
name string
child []dirTreeNode
}
var iCount int = 0
//遞歸遍歷文件目錄
func getDirTree(pathName string) (dirTreeNode, error) {
rd, err := ioutil.ReadDir(pathName)
if err != nil {
log.Fatalf("Read dir '%s' failed: %v", pathName, err)
}
var tree, childNode dirTreeNode
tree.name = pathName
var name, fullName string
for _, fileDir := range rd {
name = fileDir.Name()
fullName = pathName + "/" + name
if fileDir.IsDir() {
childNode, err = getDirTree(fullName)
if err != nil {
log.Fatalf("Read dir '%s' failed: %v", fullName, err)
}
} else {
childNode.name = name
childNode.child = nil
//讀取文件內容並打印
readLine(fullName, processLine)
iCount++
}
tree.child = append(tree.child, childNode)
}
return tree, nil
}
//遞歸打印文件目錄
func printDirTree(tree dirTreeNode, prefix string) {
fmt.Println(prefix + tree.name)
if len(tree.child) > 0 {
prefix += "----"
for _, childNode := range tree.child {
printDirTree(childNode, prefix)
}
}
}
func processLine(line []byte) {
os.Stdout.Write(line)
}
// read one file and use hookfn to process each line
func readLine(filePth string, hookfn func([]byte)) error {
f, err := os.Open(filePth)
if err != nil {
return err
}
defer f.Close()
bfRd := bufio.NewReader(f)
for {
line, err := bfRd.ReadBytes('\n')
hookfn(line) //放在錯誤處理前面,即使發生錯誤,也會處理已經讀取到的數據。
if err != nil { //遇到任何錯誤立即返回,並忽略 EOF 錯誤信息
if err == io.EOF {
return nil
}
return err
}
}
}
func main() {
dirName := "Users/"
tree, err := getDirTree(dirName)
if err != nil {
log.Fatalln("read dir", dirName, "fail: ", err)
}
fmt.Printf("\n")
fmt.Println("File Count:", iCount)
printDirTree(tree, "")
}
以上用的是ioutil.ReadDir的方法,然後用range遍歷目錄節點的list
ReadDir 函數
func ReadDir(dirname string) ([]os.FileInfo, error)
讀取 dirname 指定的目錄, 並返回一個根據文件名進行排序的目錄節點列表。
遍歷的過程可以用另一個方法:
使用filepath.Walk包中的功能path/filepath 它遍歷一個文件樹
filepath.WalkFunc,爲樹中的每個文件或目錄調用一個類型的函數,包括根。
文件按詞彙順序走。
不遵循符號鏈接。
此示例中的代碼列出了以當前目錄爲根的文件樹中所有文件和目錄的路徑和大小。
err := filepath.Walk(".",
func(path string, info os.FileInfo, err error) error {
if err != nil {
return err
}
fmt.Println(path, info.Size())
return nil
})
if err != nil {
log.Println(err)
}
另:
關於寫文件
WriteFile方法:
func check(e error) {
if e != nil {
panic(e)
}
}
var d1 = []byte(wireteString);
err2 := ioutil.WriteFile(“./output2.txt”, d1, 0666) //寫入文件(字節數組)
check(err2)
WriteFile將data寫入到filename指定的文件中。如果文件不存在,WriteFile將會創建該文件,且文件的權限是perm;如果文件存在,先清空文件內容再寫入。
WriteString方法:
var testString = “測試n”
var filename = “./output1.txt”;
var f *os.File
var err1 error;
if checkFileIsExist(filename) { //如果文件存在
f, err1 = os.OpenFile(filename, os.O_APPEND, 0666) //打開文件
fmt.Println(“文件存在”);
}else {
f, err1 = os.Create(filename) //創建文件
fmt.Println(“文件不存在”);
}
check(err1)
n, err1 := io.WriteString(f, testString ) //寫入文件(字符串)
check(err1)
fmt.Printf(“寫入 %d 個字節n”, n);
另:
str2 := "hello" data2 := []byte(str2) fmt.Println(data2) str2 = string(data2[:])