ljzsdut
GitHubToggle Dark/Light/Auto modeToggle Dark/Light/Auto modeToggle Dark/Light/Auto modeBack to homepage

文件操读写作

文件操作

文件操作

主要有三个模块设计到了文件操作:os,bufio,ioutil。

​ 打开文件:os.Openfile()、os.Open()、os.Create()

​ 读写文件:无论使用os还是bufio模块进行读写,都需要先使用os模块打开文件

​ os:(直接对fd进行操作,读取操作可能会把多字节字符截断)

​ bufio:具有缓冲区,效率高。适合大文件读写。

​ ioutil无需事先打问文件,直接将整个文件拷贝到内存进行读写操作。适合小文件读写,例如配置文件。

package main

import (
	"bufio"
	"fmt"
	"io"
	"io/ioutil"
	"os"
)

func method1() { //os模块
    // 创建文件
    // os.Create() 文件不存在则创建;文件存在则清空。
	// 打开文件
	//file, err := os.Open("./test.txt") // os.Open()打开的文件只能用于读取,不能用于写入,等同于os.OpenFile("./test.txt",O_RDONLY,0)
    
	file, err := os.OpenFile("./t1.txt", os.O_RDWR|os.O_TRUNC|os.O_CREATE, 0666) // os.OpenFile()使用指定的模式(可以指定多种)和文件权限打开文件。
	/*
	指定模式:
	os.O_RDONLY		只读
	os.O_WRONLY		只写
	os.O_RDWR		读写
	
	os.O_CREATE		创建
	os.O_APPEND		追加(默认从文件头开始写入)
	os.O_TRUNC		清空
	可以采用多种模式组合
	os.O_WRONLY|os.O_CREATE 只写(从文件头开始写,会覆盖部分文件或全部文件)/新建
	os.O_WRONLY|os.O_TRUNC|os.O_CREATE  只写(清空)/新建
	os.O_RDWR|os.O_APPEND|os.O_CREATE	读写(追加)/新建
	os.O_RDONLY		只读
	 */
	if err !=nil{
		fmt.Println("文件打开失败:",err)
		return
	}
	// 文件打开成功后的操作
	defer file.Close()


	//os模块

    // 写
	file.WriteString("浮世三千,吾爱有三\r\n日、月和你\r\n日为朝,月为暮,卿为朝朝暮暮\r\n")
	file.Write([]byte("大河向东流\r\n天上的星星参北斗\r\n"))
	file.sync()  // 将文件系统缓冲区内容写入磁盘

    // 读
    file.Seek(0,0)   // 修改读写位置:file.Seek(offset,io.SeekStart|io.SeekCurrent|io.SeekEnd),offset可为负数;返回值为相对文件头的偏移量
	bytes := make([]byte, 128)
	for {
		n, err := file.Read(bytes) // 由于[]byte的长度是128,所以会从文件中读取128个字节保存到temp中。而且会发生字符的截断导致出现乱码。所以不适合读取文本,适合读取二进制数据。
		if err==io.EOF{
			fmt.Println("文件读取完毕")
			return
		}
		if err!=nil{
			fmt.Println("文件读取失败",err)
			return
		}
		fmt.Println("读取文件字节数:",n)
		fmt.Println(string(bytes))
	}

}


func method2(){//bufio模块
	// 打开文件
	//file, err := os.Open("./test.txt") // os.Open()打开的文件只能用于读取,不能用于写入
	file, err := os.OpenFile("./t2.txt", os.O_RDWR|os.O_APPEND|os.O_CREATE, 0666) // os.OpenFile()使用指定的模式和属主打开文件。
	if err !=nil{
		fmt.Println("文件打开失败:",err)
		return
	}
	// 文件打开成功后的操作
	defer file.Close()

	//bufio模块
	writer := bufio.NewWriter(file)
	writer.WriteString("锄禾日当午\r\n")
	writer.WriteString("汗滴禾下土\r\n")
	writer.WriteString("谁知盘中餐\r\n")
	writer.WriteString("粒粒皆辛苦\r\n")
	writer.Flush()  // 刷新缓冲区数据到文件中


	file.Seek(0,0)  // 将读/写的位置设置成文件开头,开始读取文件
	reader := bufio.NewReader(file)
    // 接下来,就从reader缓冲区中读取数据
	for{
        s, err := reader.ReadString('\n')  // 读取到指定的分割符。指定字符处,类似ReadBytes()
		if err==io.EOF{ // 错误的一种,文件读取完毕
			fmt.Println("文件读取完毕")
			return
		}
		if err!=nil {
			fmt.Println("文件读取失败",err)
			return
		}
		fmt.Print(s)
	}
}


func method3(){//ioutil模块,ioutil.ReadFile()函数定义为一次性读取整个文件到内存,它不会将读取返回的EOF视为应报告的错误。此操作文件无需打开和关闭
	//ioutil写文件
	ioutil.WriteFile("./t3.txt",[]byte("I love three things in this world.\r\n" +
		"Sun moon and you.\r\n" +
		"Sun for morning. moon for night.\r\n" +
		"and you forever.\r\n"),0666)

	//ioutil读取文件
	bytes, err := ioutil.ReadFile("./t3.txt")
	if err!=nil{
		fmt.Println("文件读取错误",err)
		return
	}
	fmt.Println(string(bytes))
}


func main() {
	fmt.Println("====os模块读写文件======")
	method1()
	fmt.Println("====bufio模块读写文件======")
	method2()
	fmt.Println("====ioutil模块读写文件======")
	method3()
}

推荐示例:os.Openfile()打开文件;bufio读写文件

func main() {
	filename := "./test.txt"
	file, err := os.OpenFile(filename, os.O_CREATE|os.O_APPEND|os.O_RDWR, 0666)
	if err != nil {
		fmt.Println("文件打开失败:", err)
		return
	}
	//文件打开成功后的操作
	defer file.Close()

    // 写操作
	writer := bufio.NewWriter(file)
	writer.Write([]byte("hello\r\n"))
	writer.WriteString("World\r\n")
	writer.Flush()

    // 读操作
	file.Seek(0,io.SeekStart)
	reader := bufio.NewReader(file)
	for{
		s, err := reader.ReadString('\n')  // 读取到指定的分割符。指定字符处
		if err==io.EOF{ // 错误的一种,文件读取完毕
			fmt.Println("文件读取完毕")
			return
		}
		if err!=nil {
			fmt.Println("文件读取失败:",err)
			return
		}
		fmt.Print(s)
	}
}

目录操作

目录也是一直特殊的文件,其内容称之为目录项。所以目录也使用os.OpenFile()函数进行打开操作。只不过需要注意的是打开模式为os.O_RDONLY,权限为os.ModeDir

func main() {
	dirname := `d:\Users`
	file, err := os.OpenFile(dirname, os.O_RDONLY, os.ModeDir)
	if err != nil {
		fmt.Println("目录打开失败:", err)
		return
	}
	//文件打开成功后的操作
	defer file.Close()
	infos, err := file.Readdir(-1)
	if err != nil {
		fmt.Println("读取目录的目录项失败:",err)
		return
	}
	for _, info := range infos {
		if info.IsDir() {
			fmt.Printf("%s 是个目录",info.Name())
		}
	}
}

执行shell命令

func shell(path string, name string, arg ...string) {
	cmd := exec.Command(name, arg...)
	cmd.Dir = path
	out, err := cmd.CombinedOutput()
	if err != nil {
    fmt.Errorf("[Error]执行"+arg[0]+"操作失败:%s",string(out[:])+err.Error())
		os.Exit(1)
	}
}