golang文件操作

文件操作

写文件

io/write_file.go

package io

import (
	"fmt"
	"os"
)

func WriteFile() {
    // 如果使用go test 则相对路径是相对于xxx_test.go 文件的路径
    // 如果使用go run 或者编辑后直接运行,则相对路径是相对于执行命令所在的路径
	if fout, err := os.OpenFile("verse.txt", os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0o666); err != nil {
		fmt.Printf("open file failed: %s\n", err.Error())
	} else {
		defer fout.Close()
		fout.WriteString("纳兰性德\n")
		fout.WriteString("明月多情应笑我")
		fout.WriteString("\n")
		fout.WriteString("笑我如今")
		fout.WriteString("\n")
	}
}
/*
os.O_CREATE  创建文件 如果删除,文件不存在就保存
os.O_TRUNC   清空写入
os.O_APPEND  追加写入
os.O_WRONLY  只写操作
0o666 权限
*/

io/io_test.go

package io_test

import (
	"goPractice/io"
	"testing"
)

func TestWriteFile(t *testing.T) {
	io.WriteFile()
}

运行测试

go test -v ./io -run=^TestWriteFile$

verse.txt

纳兰性德
明月多情应笑我
笑我如今

读文件

io/read_file.go

package io

import (
	"fmt"
	"io"
	"os"
)

func ReadFile() {
	if fin, err := os.Open("verse.txt"); err != nil {
		fmt.Printf("open file faild: %s\n", err.Error())
	} else {
		defer fin.Close()
		bs := make([]byte, 200)
		fin.Read(bs)
		fmt.Println(string(bs))

		// 一个汉字占三个字节
		fin.Seek(0, 0) // 跳过前10个字节,从起始位置开始
		fin.Read(bs)
		fmt.Println(string(bs))

		fin.Seek(0, 0) // 重新回到起始位置
		const BATCH = 10
		bufer := make([]byte, BATCH)
		for {
			n, err := fin.Read(bufer)
			if n > 0 {
				fmt.Println(bufer[0:n])
			}
			if err == io.EOF {
				break
			}
		}
	}
}

io/io_test.go

package io_test

import (
	"goPractice/io"
	"testing"
)

func TestReadFile(t *testing.T) {
	io.ReadFile()
}

运行测试

go test -v ./io -run=^TestReadFile$

使用bufio读写文件

写文件

package io

import (
	"bufio"
	"fmt"
	"os"
)

func WriteFileWithBuffer() {
	if fout, err := os.OpenFile("verse.txt", os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0o666); err != nil {
		fmt.Printf("open file failed: %s\n", err.Error())
	} else {
		defer fout.Close()
		writer := bufio.NewWriter(fout)
		writer.WriteString("纳兰性德\n")
		writer.Write([]byte("明月多情应笑我\n"))
		writer.WriteString("笑我如今\n")
		writer.Flush() // 写入文件
	}
}

读文件

package io

import (
	"bufio"
	"fmt"
	"io"
	"os"
	"strings"
)

func ReadFileWithBuffer() {
	if fin, err := os.Open("verse.txt"); err != nil {
		fmt.Printf("open file faild: %v\n", err)
	} else {
		defer fin.Close()
		reader := bufio.NewReader(fin)
		for {
			line, err := reader.ReadString('\n')
			if len(line) > 0 {
				line = strings.TrimRight(line, "\n") // 去掉多余的换行符
				fmt.Println(line)
			}
			if err == io.EOF { // End Of File
				break
			}
		}

	}
}

test

func TestReadFileWithBuffer(t *testing.T) {
	io.ReadFileWithBuffer()
}

func TestWriteFileWithBuffer(t *testing.T) {
	io.WriteFileWithBuffer()
}

go test -v ./io -run=^TestReadFileWithBuffer$
go test -v ./io -run=^TestWriteFileWithBuffer$

文件管理和目录遍历

package io

import (
	"fmt"
	"io/fs"
	"os"
	"path/filepath"
)

func CreateFile(fileName string) {
	os.Remove(fileName) // 操作系统负责管理文件,相关操作用os  读写流用io
	if file, err := os.Create(fileName); err != nil {
		fmt.Printf("create file failed: %v\n", err)
	} else {
		defer file.Close()
		file.Chmod(0o666)
		fmt.Printf("fd=%d\n", file.Fd()) // FD是有上限的,I/O流不用了要及时关闭包括文件和网络IO
		file.WriteString("多情应笑我\n")
		info, _ := file.Stat()
		fmt.Printf("is dir %t\n", info.IsDir())
		fmt.Printf("modify time %s\n", info.ModTime())
		fmt.Printf("mode %v\n", info.Mode())
		fmt.Printf("file name %s\n", info.Name())
		fmt.Printf("size  %dB\n", info.Size())
	}

	os.Mkdir("../data/sys", os.ModePerm)
	os.MkdirAll("../data/sys/a/b/c", os.ModePerm)
	os.Rename("../data/sys/a", "../data/sys/p")
	os.Rename("../data/sys/p/b/c", "../data/sys/p/c")

	// os.Remove("../data/sys")    // 必须是一个空目录
	// os.RemoveAll("../data/sys") // 可以删除非空目录
}

// 遍历一个目录
func WalkDir(path string) error {
	filepath.Walk(path, func(subpath string, info fs.FileInfo, err error) error {
		if err != nil {
			return err
		}
		if info.Mode().IsDir() && subpath != path {
			fmt.Printf("path is dir %s\n", subpath)
		} else if info.Mode().IsRegular() {
			fmt.Printf("path is file %s basename %s\n", subpath, info.Name())
		}
		return nil
	})
	return nil
}