go语言基础学习(八)- I/O操作

客户不应假定它们对于并行执行是安全的。

io库比较常用的接口有三个,分别是Reader,Writer和Closer。

1.1 Reader

type Reader interface {
        Read(p []byte) (n int, err error)
}

io.Reader 表示一个读取器,它将数据从某个资源读取到传输缓冲区。在缓冲区中,数据可以被流式传输和使用。

  • 对于要用作读取器的类型,它必须实现 io.Reader 接口的唯一一个方法 Read(p []byte)。
  • 换句话说,只要实现了 Read(p []byte) ,那它就是一个读取器。
  • Read() 方法有两个返回值,一个是读取到的字节数,一个是发生错误时的错误

通过 string.NewReader(string) 创建一个字符串读取器,然后流式地按字节读取:

 

package day11

import (
	"io"
	"log"
	"os"
	"strings"
)

func D111() {
	reader := strings.NewReader("dacheng test 123234")
	// 每次读取4个字节
	p := make([]byte, 4)
	for {
		n, err := reader.Read(p)

		if err != nil {
			// 剩下的内容不够4个字节
			if err == io.EOF {
				log.Printf("读完了:eof错误 : %d", n)
				break
			}
			log.Printf("其他错误: %v", err)
			os.Exit(2)
		}
		log.Printf("[读取到的字节数 %d][内容: %v]", n, string(p[:n]))
	}
}
package main

import (
	"go_pric/day11"
)

func main() {
	day11.D111()
}
  • 最后一次返回的 n 值有可能小于缓冲区大小。
  • io.EOF 来表示输入流已经读取到头

 

 

1.1.1 文件操作相关API

  • func Create(name string) (file *File, err Error)
    
    • 根据提供的文件名创建新的文件,返回一个文件对象,默认权限是0666
  • func NewFile(fd uintptr, name string) *File
    
    • 根据文件描述符创建相应的文件,返回一个文件对象
  • func Open(name string) (file *File, err Error)
    
    • 只读方式打开一个名称为name的文件
  • func OpenFile(name string, flag int, perm uint32) (file *File, err Error)
    
    • 打开名称为name的文件,flag是打开的方式,只读、读写等,perm是权限
  • func (file *File) Write(b []byte) (n int, err Error)
    
    • 写入byte类型的信息到文件
  • func (file *File) WriteAt(b []byte, off int64) (n int, err Error)
    
    • 在指定位置开始写入byte类型的信息
  • func (file *File) WriteString(s string) (ret int, err Error)
    
    • 写入string信息到文件
  • func (file *File) Read(b []byte) (n int, err Error)
    
    • 读取数据到b中
  • func (file *File) ReadAt(b []byte, off int64) (n int, err Error)
    
    • 从off开始读取数据到b中
  • func Remove(name string) Error
    
    • 删除文件名为name的文件

1.1.2 读文件

os.Open()函数能够打开一个文件,返回一个*File和一个err。对得到的文件实例调用Close()方法能够关闭文件

type Closer interface {
    Close() error
}

 

package day11

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

func D112() {
	// 打开文件
	file, err := os.Open("day11/t.txt")
	if err != nil {
		fmt.Println("open file err :", err)
		return
	}
	// 让出goroutine,先去执行下面的
	defer file.Close()
	// 定义接收文件读取的字节数组
	var buf [128]byte
	// 接收读取的文件
	var content []byte

	for {
		n, err := file.Read(buf[:])
		if err == io.EOF {
			// 读取结束 跳出循环
			break
		}

		if err != nil {
			fmt.Println("read file err", err)
			return
		}
		// buf[:n]...   这个是固定的Y欧诺个发
		content = append(content, buf[:n]...)
	}
	// 将读取的内容转换成string输出
	fmt.Println(string(content))

}

 

package main

import (
	"go_pric/day11"
)

func main() {
	day11.D112()
}

1.2 Writer

和Reader有异曲同工

type Writer interface {
    //Write() 方法有两个返回值,一个是写入到目标资源的字节数,一个是发生错误时的错误。
    Write(p []byte) (n int, err error)
}
  • io.Writer 表示一个写入器,它从缓冲区读取数据,并将数据写入目标资源。
  • 对于要用作编写器的类型,必须实现 io.Writer 接口的唯一一个方法 Write(p []byte)
  • 同样,只要实现了 Write(p []byte) ,那它就是一个编写器。

1.3 bufio

  • bufio包实现了带缓冲区的读写,是对文件读写的封装
  • bufio缓冲写数据
模式含义
os.O_WRONLY只写
os.O_CREATE创建文件
os.O_RDONLY只读
os.O_RDWR读写
os.O_TRUNC清空
os.O_APPEND追加

 

package day11

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

func Wr() {
	// 参数2 : 打开模式,所有模式的含义在上述表格
	// 参数3 是权限控制
	// w 写 r读 x执行, w 2 r 4 x 1
	// 0666 特殊权限位, 拥有者位, 同组用户位,其余用户位
	file, err := os.OpenFile("./test.txt", os.O_CREATE|os.O_RDONLY, 0666)
	if err != nil {
		fmt.Println(err)
		return
	}
	defer file.Close()
	// 获取writer对象
	writer := bufio.NewWriter(file)
	for i := 0; i < 10; i++ {
		writer.WriteString("hello\n")
	}
	// 刷新缓冲区,强制写出
	writer.Flush()
}

func Re() {
	file, err := os.Open("./test.txt")
	if err != nil {
		fmt.Println(err)
		return
	}
	defer file.Close()
	read := bufio.NewReader(file)
	for {
		line, _, err := read.ReadLine()
		if err == io.EOF {
			break
		}
		if err != nil {
			return
		}
		fmt.Println(string(line))
	}

}
func D114() {
	Wr()
	Re()
}

1.4 ioutil工具包 (ioutil.WriteFile is deprecated: As of Go 1.16, this function simply calls [os.WriteFile].)

  • ioutil库包含在io目录下,它的主要作用是作为一个工具包,里面有一些比较实用的函数
  • 比如 ReadAll(从某个源读取数据)、ReadFile(读取文件内容)、WriteFile(将数据写入文件)、ReadDir(获取目录)
package day11

import (
	"fmt"
	"io/ioutil"
)

func We() {
	err := ioutil.WriteFile("./t.txt", []byte("this is a lonely road\n"), 0666)
	if err != nil {
		fmt.Println(err)
		return
	}

}

func Re1() {
	content, err := ioutil.ReadFile("./t.txt")
	if err != nil {
		fmt.Println(err)
		return
	}
	fmt.Println(string(content))
}

func D115() {
	We()
	Re1()
}

1.5 实现一个cat命令

使用文件操作相关知识,模拟实现linux平台cat命令的功能。

package day11

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

// cat命令实现
func Cat(r *bufio.Reader) {
	for {
		line, _, err := r.ReadLine()
		if err == io.EOF {
			break
		}
		if err != nil {
			return
		}
		fmt.Println(string(line))
		//注意是字符所以使用单引号
		buf, err := r.ReadBytes('\n')
		if err == io.EOF {
			break
		}
		fmt.Fprintf(os.Stdout, "%s", buf)
	}
}

func D116() {
	// 解析命令行参数
	flag.Parse()
	if flag.NArg() == 0 {
		// 入股没有参数默认从标准输入读取内容
		Cat(bufio.NewReader(os.Stdin))
	}
	// 依次读取每个指定文件的内容并打印到终端
	for i := 0; i < flag.NArg(); i++ {
		// 获取第i个文件名
		f, err := os.Open(flag.Arg(i))
		if err != nil {
			fmt.Fprintf(os.Stdout, "reading form %s failed err:%v\n", flag.Arg(i), err)
			continue
		}
		Cat(bufio.NewReader(f))
	}
}

  • 21
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值