【Go语言学习】——文件操作

文件操作


参考博客

  • 文件读取

    使用os.Open()打开文件后只能够读,不能够用于写,注意打开文件后返回错误和文件指针,那么判断错误要写在文件关闭的前面,因为有错误的话文件为空,不能执行close。

    package main
    
    import (
    	"bufio"
    	"fmt"
    	"io"
    	"io/ioutil"
    	"os"
    )
    
    // 利用read读取文件,可以自定义每次读取的位数
    func ReadFromRead() {
    	//open函数里可以是绝对路径,也可以是相对路径(从当前文件夹目录下)
    	fileObj, err := os.Open("./main.go")
    	if err != nil {
    		fmt.Printf("Open file failed,err:%v", err)
    		return
    	}
    	//关闭文件可以用defer来确保最后关闭文件
    	defer fileObj.Close()
    	//用循环读完文件所有内容
    	//读文件 read()参数为接受读出来的数据的[]byte,最大读取长度为字节切片的长度,两个返回值一个是实际读取长度和错误
    	tmp := make([]byte, 128)
    	for {
    		n, err := fileObj.Read(tmp)
    		if err == io.EOF {
    			fmt.Println("读完了")
    		}
    		if err != nil {
    			fmt.Printf("Open file failed,err:%v", err)
    			return
    		}
    		fmt.Printf("读取了%d个字节\n", n)
    		// fmt.Printf("%s", string(tmp[:n]))
    		fmt.Println(string(tmp[:n]))
    		//当读取的字节少于128个字节时,说明没有剩余未读取的字节
    		if n < 128 {
    			return
    		}
    	}
    }
    
    //利用bufio创建一个reader实现读取,可以实现一行一行的读取
    func ReadFromBufio() {
    	//open函数里可以是绝对路径,也可以是相对路径(从当前文件夹目录下)
    	fileObj, err := os.Open("./main.go")
    	if err != nil {
    		fmt.Printf("Open file failed,err:%v", err)
    		return
    	}
    	//关闭文件可以用defer来确保最后关闭文件
    	defer fileObj.Close()
    	// 创建一个用来从文中读取内容的对象
    	reader := bufio.NewReader(fileObj)
    	for {
    		line, err := reader.ReadString('\n') //换行符表示每次只读一行,注意是字符
    		if err == io.EOF {
    			fmt.Println("读完了")
    			return
    		}
    		if err != nil {
    			fmt.Printf("read line failed,err:%v", err)
    			return
    		}
    		//自带换行
    		fmt.Print(line)
    	}
    }
    
    //可以一次性读取文件的所有内容,
    //不用先声明一个file类型,自动打开和关闭文件
    func ReadFromIoutil() {
    
    	ret, err := ioutil.ReadFile("./main.go")
    	if err != nil {
    		fmt.Printf("read line failed,err:%v", err)
    		return
    	}
    	//注意返回的是[]byte,打印时转换为字符串再打印
    	fmt.Println(string(ret))
    }
    
    func main() {
    	// ReadFromRead()
    	// ReadFromBufio()
    	ReadFromIoutil()
    }
    
    
  • 文件写入

    os.OpenFile()能够以指定模式打开文件,从而实现文件写入功能。打开文件模式由os.OpenFile()的第二个参数flag决定,第三个参数为权限,为一个八进制数,在linux环境下常用,window下不常用,最好乱写一个没有权限。flag各个含义如下:

    模式含义
    os.O_WRONLY只写
    os.O_CREATE创建文件(文件不存在会自动创建)
    os.O_RDONLY只读
    os.O_RDWR读写
    os.O_TRUNC清空(与追加智能有一个)
    os.O_APPEND追加
    package main
    
    import (
    	"bufio"
    	"fmt"
    	"io/ioutil"
    	"os"
    )
    //使用Os.OpenFile用相应模式打开的文件才能够写
    //使用write写入信息
    func writeDemo() {
    	//os.OpenFile的第二个参数本质上是一个数,可以看成是不同的二进制数,不同的位置为1表示不同的含义,所以可以用|来连接表示多种模式并行
    	fileObj, err := os.OpenFile("./xxx.txt", os.O_WRONLY|os.O_TRUNC|os.O_CREATE, 0644)
    	if err != nil {
    		fmt.Printf("Open file failed,err:%v", err)
    		return
    	}
    	//使用write写信息,参数是[]byte,所以要注意类型转换
    	fileObj.Write([]byte("Hello,卡卡1\n"))
    	//使用writeString写信息,参数是一个string
    	fileObj.WriteString("Hello,zq")
    	defer fileObj.Close()
    }
    
    // 使用Bufio缓存写入
    func writeDemo2() {
    	//os.OpenFile的第二个参数本质上是一个数,可以看成是不同的二进制数,不同的位置为1表示不同的含义,所以可以用|来连接表示多种模式并行
    	fileObj, err := os.OpenFile("./xxx.txt", os.O_WRONLY|os.O_TRUNC|os.O_CREATE, 0644)
    	if err != nil {
    		fmt.Printf("Open file failed,err:%v", err)
    		return
    	}
    	defer fileObj.Close()
    	//创建一个写的对象
    	wr := bufio.NewWriter(fileObj)
    	//将数据先写入缓存
    	wr.WriteString("Hello,卡卡2")
    	//将缓存的内容写进文件
    	wr.Flush()
    }
    
    //使用ioutil写入文件,注意是字符切片,要类型转换
    func writeDemo3() {
    	str := "Hello,卡卡3"
    	err := ioutil.WriteFile("./xxx.txt", []byte(str), 0666)
    	if err != nil {
    		fmt.Println("write file failed,err", err)
    		return
    	}
    }
    func main() {
    	// writeDemo()
    	// writeDemo2()
    	writeDemo3()
    }
    
  • 使用bufio读取标准输入

    package main
    
    import (
    	"bufio"
    	"fmt"
    	"os"
    )
    
    // scan默认空格为换行符,所以不能直接输入含有空格的内容
    func useScan() {
    	var s string
    	fmt.Print("请输入内容:")
    	fmt.Scanln(&s)
    	fmt.Printf("你输入的内容是%s\n", s)
    }
    
    //利用bufio可以往标准输入或输出中写,即实现从终端中读取输入或者打印数据至终端上
    func useBufio() {
    	var s string
    	//os.Stdin表示为标准输入,即从终端中读取
    	//newReader的参数是接口类型
    	reader := bufio.NewReader(os.Stdin)
    	fmt.Print("请输入内容:")
    	//表示以换行符结束
    	s, _ = reader.ReadString('\n')
    	fmt.Printf("你输入的内容是%s\n", s)
    }
    
    func main() {
    	useScan()
    	useBufio()
    }
    
  • 实现copyfile

    package main
    
    import (
    	"fmt"
    	"io"
    	"os"
    )
    
    func copyFile(dstName, srcName string) (written int64, err error) {
    	src, err := os.Open(srcName)
    	if err != nil {
    		fmt.Printf("open %s failed,err:%v.\n", srcName, err)
    		return
    	}
    	defer src.Close()
    	dst, err := os.OpenFile(dstName, os.O_CREATE|os.O_WRONLY, 0644)
    	if err != nil {
    		fmt.Printf("open %s failed,err:%v.\n", dstName, err)
    		return
    	}
    	defer dst.Close()
    	return io.Copy(dst, src)
    }
    
    func main() {
    	_, err := copyFile("dst.txt", "src.txt")
    	if err != nil {
    		fmt.Printf("copy fail:%v ", err)
    		return
    	}
    	fmt.Println("copy succeed")
    }
    
  • 中间插入文件内容

    使用seek可以移动光标,但是移动的是位数,换行符占2位,不方便,通过建立临时存储区存储前半部分内容,插入内容后再加上后续内容是通用方法,这种方法使用read读取的是字符数,换行符只占1个字符

    package main
    
    import (
    	"fmt"
    	"io"
    	"os"
    )
    
    //利用seek函数可以选择起始操作位置,其中第一个参数表示相对偏移量,第二个参数表示相对位置,0为开头,1为当前位置,2为末尾
    //注意移动到这个位置后直接执行写操作会覆盖原来的值,因此需要新建临时文件保存值
    func insert() {
    	fileobj, err := os.OpenFile("./xxx.txt", os.O_RDWR, 0644)
    	if err != nil {
    		fmt.Printf("open file failed,err:%v", err)
    		return
    	}
    	//创建临时文件存储前面内容,再插入内容,然后读入后面的内容,从而实现向中间插入内容
    	tmp, err := os.OpenFile("./tmp.txt", os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0644)
    	if err != nil {
    		fmt.Printf("creat tempFile failed, err:%v", err)
    		return
    	}
    	//建立缓冲区,读取前部分内容,注意换行符占一个字节
    	buf := make([]byte, 2)
    
    	n, err := fileobj.Read(buf)
    	if err != nil {
    		fmt.Printf("read file failed err:%v", err)
    		return
    	}
    	//将缓冲区内容写入临时文件
    	tmp.Write(buf[:n])
    	//写入插入内容
    	tmp.Write([]byte("b\n"))
    	//写入原文件的后续内容
    	last := make([]byte, 1024)
    	for {
    		n, err := fileobj.Read(last)
    		if err == io.EOF {
    			break
    		} else if err != nil {
    			fmt.Printf("read file failed err:%v", err)
    			return
    		}
    		tmp.Write(last[:n])
    	}
    	fileobj.Close()
    	tmp.Close()
    	//通过重命名为同样名字将原来的文件覆盖
    	os.Rename("./tmp.txt", "./xxx.txt")
    }
    
    func main() {
    	insert()
    }
    
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值