Go笔记-文件
Go笔记-文件
漂泊尘埃 发表于10个月前
Go笔记-文件
  • 发表于 10个月前
  • 阅读 13
  • 收藏 1
  • 点赞 0
  • 评论 0

腾讯云 技术升级10大核心产品年终让利>>>   

创建和删除目录

	os.Mkdir("file", os.ModePerm)
	os.MkdirAll("file2/sub1/sub2", os.ModePerm)
	err := os.Remove("file2/sub1") // cann't remove
	if err != nil {
		fmt.Println(err)
	}
	os.RemoveAll("file2")
	os.Remove("file")

linux中文件权限的表示

可读-可写-可执行表示为111,没有权限使用0

分组:自己-同组用户-其他用户,每组3位数,如110 110 100即664,表示自己可读写,同组用户可读写,其他用户可读。

创建并写文件

	fout, err := os.Create("t1.txt")
	if err != nil {
		fmt.Println(err)
		return
	}
	defer fout.Close()

	for i := 0; i < 10; i++ {
		fout.WriteString("just 测试 string.\r\n")
		fout.Write([]byte("just 测试 []byte.\r\n"))
	}

打开并读文件

	f, err := os.Open("t1.txt")
	if err != nil {
		fmt.Println(err)
		return
	}
	defer f.Close()

	buf := make([]byte, 1024)
	for {
		n, _ := f.Read(buf)
		if n == 0 {
			break
		}
		os.Stdout.Write(buf[:n])
	}

也可以使用 ioutil.ReadAll(f),它会把整个文件都读到内存中。

按行读取文件

func FileRead(filePath string) (err error) {
	file, err := os.OpenFile(filePath, os.O_RDONLY, os.ModePerm)
	if err != nil {
		return
	}
	defer file.Close()

	reader := bufio.NewReader(file)
	var (
		line      string
		lineCount int
	)
	for err == nil {
		line, err = reader.ReadString('\n')
		line = strings.TrimSpace(line) // line包含换行符
		if line == "" {
			continue
		}
		lineCount++
		if lineCount > 10 {
			break
		}
		fmt.Println(lineCount, line)
	}
	if err == io.EOF {
		err = nil
	}
	return
}

使用bufio.NewScanner

	input := bufio.NewScanner(f)
    for input.Scan() {
        counts[input.Text()]++ // input.Text()不包含换行符
    }
// readFromFile will read all lines from the given filename and write them to a
// string array, if filename is empty readFromFile returns and empty string
// array
func readLinesFromFile(filename string) ([]string, error) {
	if filename == "" {
		return nil, nil
	}

	file, err := os.Open(filename)
	if err != nil {
		return nil, err
	}
	defer file.Close()

	var lines []string

	scanner := bufio.NewScanner(file)
	for scanner.Scan() {
		lines = append(lines, scanner.Text())
	}

	if err := scanner.Err(); err != nil {
		return nil, err
	}

	return lines, nil
}

删除文件

删除文件和删除目录是同一个方法

	err := os.Remove("t1.txt")
	if err != nil {
		fmt.Println(err)
	} else {
		fmt.Println("removed.")
	}

删除目录时要求目录是空的。

覆盖式写文件(不存在时创建)

	file, err := os.OpenFile(fileName, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, os.ModePerm)
	if err != nil {
		return
	}
	defer file.Close()

	_, err = file.Write(data)

遍历目录

遍历所有后代文件或目录

	filepath.Walk("/a/b/c", func(path string, info os.FileInfo, err error) error {
		// do something...
		return nil
	})

path是文件的全路径

跳过目录

return filepath.SkipDir

遍历子文件或目录

file, _ := os.Open(path)
children, _ := file.Readdir(-1)

或者使用ioutil.ReadDir()

以树形显示目录树

func WalkSubDir() (t *tree.TreeNode) {
	root := "/a/b/c"
	t = tree.NewTreeNode(nil, root)

	walkDirToTree(t, root)
	return t
}

func walkDirToTree(t *tree.TreeNode, path string) {
	file, _ := os.Open(path)
	fileInfo, _ := file.Stat()
	node, _ := t.AppendChild(fileInfo.Name())

	// 文件
	if !fileInfo.IsDir() {
		return
	}

	// 目录
	children, _ := file.Readdir(-1)
	for _, child := range children {
		walkDirToTree(node, filepath.Join(path, child.Name()))
	}
}

使用正则搜索文件

	dir := "/a"
	files, err := filepath.Glob(dir + "/*.md")
	if err != nil {
		panic(err)
	}

	for _, d := range files {
		fmt.Printf("match %10s \n", d)
	}

输出示例:

match /a/a.md 

可用的正则:

pattern:
	{ term }
term:
	'*'         matches any sequence of non-Separator characters
	'?'         matches any single non-Separator character
	'[' [ '^' ] { character-range } ']'
	            character class (must be non-empty)
	c           matches character c (c != '*', '?', '\\', '[')
	'\\' c      matches character c

character-range:
	c           matches character c (c != '\\', '-', ']')
	'\\' c      matches character c
	lo '-' hi   matches character c for lo <= c <= hi

查看文档和test文件了解更多。

当前程序运行的目录

	workPath, _ = os.Getwd()
	workPath, _ = filepath.Abs(workPath)
	AppPath, _ = filepath.Abs(filepath.Dir(os.Args[0]))
  • 摘自beego
  • os.Args[0] 是运行文件的全路径
  • workPath 和 AppPath 应该是一样的,不一样的情况还不知道是怎么样的?

判断文件是否存在

func FileExists(name string) bool {
	if _, err := os.Stat(name); err != nil {
		if os.IsNotExist(err) {
			return false
		}
	}
	return true
}
  • 摘自beego
  • os.IsNotExist(err) 可判断err是不是表示不存在
  • 与之相反的是:os.IsExist(err)
  • 也可以判断目录是否存在

以列表显示目录树,可自定义根节点名称

func GetHugoContentDirList() (list []string) {
	root, err := os.Open("D:/work/hugo/mysite/content")
	if err != nil {
		return
	}
	list = append(list, "root")
	children := getChildren("root", root)
	list = append(list, children...)
	return
}

func getChildren(prefix string, parent *os.File) (children []string) {
	cFiles, err := parent.Readdir(-1)
	if err != nil {
		return
	}

	parentAbsPath, err := filepath.Abs(parent.Name())
	if err != nil {
		fmt.Println(err)
		return
	}

	for _, c := range cFiles {
		fullPath := prefix + "/" + c.Name()
		children = append(children, fullPath)
		if c.IsDir() {
			cFile, err := os.Open(filepath.Join(parentAbsPath, c.Name()))
			if err != nil {
				fmt.Println(err, c.Name())
				continue
			}
			subChildren := getChildren(fullPath, cFile)
			children = append(children, subChildren...)
		}
	}
	return
}

输出示例:

[root root/about.md root/post root/post/first.md root/post/second.md root/post/THREE.md]

复制文件

// copyFile creates dst from src, preserving file attributes and timestamps.
func copyFile(dst, src string) error {
	fi, err := os.Stat(src)
	if err != nil {
		return err
	}

	fsrc, err := os.Open(src)
	if err != nil {
		return err
	}

	if err = os.MkdirAll(filepath.Dir(dst), 0755); err != nil {
		fmt.Printf("MkdirAll(%v)\n", filepath.Dir(dst))
		return err
	}

	fdst, err := os.Create(dst)
	if err != nil {
		return err
	}

	if _, err = io.Copy(fdst, fsrc); err != nil {
		return err
	}

	if err == nil {
		err = fsrc.Close()
	}

	if err == nil {
		err = fdst.Close()
	}

	if err == nil {
		err = os.Chmod(dst, fi.Mode())
	}

	if err == nil {
		err = os.Chtimes(dst, fi.ModTime(), fi.ModTime())
	}

	return nil
}
标签: Go 文件
共有 人打赏支持
漂泊尘埃
粉丝 4
博文 35
码字总数 70992
×
漂泊尘埃
如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
* 金额(元)
¥1 ¥5 ¥10 ¥20 其他金额
打赏人
留言
* 支付类型
微信扫码支付
打赏金额:
已支付成功
打赏金额: