golang中的标准库IO操作

参考链接

输入输出的底层原理

终端其实是一个文件,相关实例如下:

  • os.Stdin:标准输入的文件实例,类型为*File
  • os.Stdout:标准输出的文件实例,类型为*File
  • os.Stderr:标准错误输出的文件实例,类型为*File
    以文件的方式操作终端:
func main() { 
  var buf [16]byte 
  os.Stdin.Read(buf[:]) 
  fmt.Println(string(buf[:])) } 

文件操作相关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 main() { 
  file, _ := os.Open("./log/2021-11-29.txt") // 以只读方式打开文件  
  fileInfo, _ := file.Stat() // 获取文件信息
  fileSize := fileInfo.Size() // 获取文件字节大小 
  buf := make([]byte, fileSize) // 创建一个buf变量 
  file.Read(buf) // 将文件内容读取到buf中 
  fmt.Println(string(buf)) // 输出 } 

输出结果:

2021/11/29 16:52:35.242112 C:/Users/mayanan/Desktop/pro_go/common_standard_library/main.go:20: 这是一条很普通的日志。 
[小王子]2021/11/29 16:52:35.242721 C:/Users/mayanan/Desktop/pro_go/common_standard_library/main.go:22: 这是一条很普通的日志。 
  • 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) WriteString(s string) (ret int, err Error) 写入string信息到文件
  • 案例:
 func main() { 
  file, _ := os.OpenFile("./log/2021-11-29.txt", os.O_APPEND, 0644)
  file.Write([]byte("哈哈哈\n")) file.WriteString("你好啊\n") }
  • func (file *File) WriteAt(b []byte, off int64) (n int, err Error) 在指定位置开始写入byte类型的信息
    案例:
func main() { 
 // If file was opened with the O_APPEND flag, WriteAt returns an error. 
 file, _ := os.OpenFile("./log/2021-11-29.txt", os.O_WRONLY, 0644) 
 file.WriteAt([]byte("你好啊\n"), 15) } 
  • func Remove(name string) Error 删除文件名为name的文件
 func main() { 
  os.Remove("./log/2021-11-29.txt") // 删除一个文件 
  os.RemoveAll("./log/") // 删除目录及目录下的所有文件 } 

打开和关闭文件

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

 package main 
import ( "fmt" "os" ) 
func main() {
   // 只读方式打开当前目录下的main.go文件 
   file, err := os.Open("./main.go") 
   if err != nil { 
      fmt.Println("open file failed!, err:", err)
     return 
} // 关闭文件 file.Close() } 

写文件

package main 
import ( "fmt" "os" )
 func main() { 
// 新建文件 
file, err := os.Create("./xxx.txt") if err != nil {
 fmt.Println(err) return
 } 
defer file.Close() 
for i := 0; i < 5; i++ { 
  file.WriteString("ab\n")
 file.Write([]byte("cd\n"))
 } 
} 

读文件

文件读取可以用file.Read()和file.ReadAt(),读到文件末尾会返回io.EOF的错误

func main() {
 // 打开文件 
file, err := os.Open("./test/t01.txt") if err != nil { fmt.Println("open file failed") 
return } 
defer file.Close()
 // 定义接收文件读取的字节数组
 var content []byte
 var buf [128]byte 
for {
 n, err := file.Read(buf[:])
 if err == io.EOF {
 // 读取结束 break
 } 
if err != nil {
 fmt.Println("Read failed") 
return
 } 
content = append(content, buf[:n]...)
 } 
fmt.Println(string(content)) }

拷贝文件(单个 main goroutine)

 func main() {
 //c := make(chan []byte, 1024)
 //wg.Add(1)
 //ReadFile(c) 
//wg.Add(1) 
//go WriteFile(c) 
//wg.Wait() 
// 删除副本 
os.Remove("./test/t01副本.txt") file, _ := os.Open("./test/t01.txt")
 buf := make([]byte, 10) 
for {
 n, err := file.Read(buf) 
if err == io.EOF {
 fmt.Println("读取完毕") 
break
 } 
if err != nil { 
fmt.Println("读取失败") 
return 
} 
fmt.Println(string(buf)) 
newFile, _ := os.OpenFile("./test/t01副本.txt", os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0644) 
newFile.Write(buf[:n]) 
} 
} 

拷贝文件(两个goroutine,一个读,一个写)

并且:读、写采用异步通道

var wg sync.WaitGroup 
func main() { 
// c通道用来传输数据 c := make(chan []byte, 1024) 
// 此处使用异步通道 
// 还需要一个通道用来传输每次写入到通道的字节个数 
bc := make(chan int, 1024) // 1024代表通道的容量 
wg.Add(1) 
go ReadFile(c, bc) 
wg.Add(1) 
go WriteFile(c, bc) 
wg.Wait()
 } 

func ReadFile(c chan []byte, bc chan int) {
 defer wg.Done()
 file, err := os.Open("./test/t01.txt") if err != nil { fmt.Println("Open file failed")
 return
 } 
defer file.Close() 
for { 
// 注意:定义buf一定要放在for循环里面 // 如果放在循环外面,buf只保存最后一次file.Read(buf)的数据,就会出现bug var buf = make([]byte, 10) // 每次读取10个字节的数据放入到通道中
 n, err := file.Read(buf) 
if err == io.EOF {
 fmt.Println("读取完毕")
 close(c) // 关闭通道
 close(bc) 
return 
} 
if err != nil {
 fmt.Println("Read file failed") 
return 
} 

bufio

  • bufio包实现了带缓冲区的读写,是对文件读写的封装
  • bufio缓冲写数据
模式 含义
os.O_WRONLY 只写
os.O_CREATE 创建文件
os.O_RDONLY 只读
os.O_RDWR 读写
os.O_TRUNC 清空
os.O_APPEND 追加
  • bufio读数据
func main() {
	//wr()
	re()
}
func re() {
	// 读文件用os.Open
	file, err := os.Open("./t01.txt")
	if err != nil {
		fmt.Println(err.Error())
		return
	}
	defer file.Close()
	// 获取reader对象
	reader := bufio.NewReader(file)
	for {
		line, _, err := reader.ReadLine()
		if err == io.EOF {
			break
		}
		if err != nil {
			fmt.Println(err.Error())
			return
		}
		fmt.Println(string(line))
	}
}
func wr() {
	// 写文件用os.OpenFile
	file, err := os.OpenFile("t01.txt", os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0644)
	if err != nil {
		fmt.Println(err.Error())
		return
	}
	defer file.Close()
	// 获取Writer对象
	writer := bufio.NewWriter(file)
	for i := 0; i < 10; i++ {
		writer.WriteString(fmt.Sprintf("hello %d\n", i))
	}
	// 刷新缓冲区,强制写出
	writer.Flush()
}

posted @ 2021-11-30 14:54  专职  阅读(195)  评论(0编辑  收藏  举报