go IO操作-文件写

go IO操作-文件写

函数介绍

os.OpenFile()函数能够以指定模式打开文件,从而实现文件写入相关功能。

func OpenFile(name string, flag int, perm FileMode) (*File, error) {}
func Create(name string) (*File, error) {}
// 本质还是OpenFile--》return OpenFile(name, O_RDWR|O_CREATE|O_TRUNC, 0666)

flag参数介绍

模式含义
os.O_WRONLY只写
os.O_CREATE创建文件
os.O_RDONLY只读
os.O_RDWR读写
os.O_TRUNC清空
os.O_APPEND追加

写入文件

File.Write(将字节写入文件)

func main() {
	file,err:=os.Create("lxx.txt")
	if err != nil {
		fmt.Println("打开文件错误:",err)
		return
	}
	defer file.Close()
	//d2 := []byte{104, 101, 108, 108, 111, 32, 119, 111, 114, 108, 100}
	//d2 := []byte("hello world")
	d2 := []byte{'h','e','l','l','o'}
	n,err:=file.Write(d2)
	if err != nil {
		fmt.Println("写入文件出错:",err)
	}
	fmt.Printf("%d字节写入文件成功",n)
}

File.WriteString(将字符串写入文件)

func main() {
	file,err:=os.Create("lxx.txt")
	if err != nil {
		fmt.Println("打开文件错误:",err)
		return
	}
	defer file.Close()
	s:="hello world"
	n,err:=file.WriteString(s)
	if err != nil {
		fmt.Println("写入文件出错:",err)
	}
	fmt.Printf("%d字节写入文件成功",n)
}

ioutil.WriteFile写入文件

func main() {
	err:=ioutil.WriteFile("lxx.txt",[]byte("lxx is nb"),0666)
	if err != nil {
		fmt.Println("写入文件出错",err)
		return
	}
}

bufio.NewWriter写入文件

func main() {
	file,err:=os.OpenFile("lxx.txt",os.O_CREATE|os.O_WRONLY,0666)
	if err != nil {
		fmt.Println("打开文件出错:",err)
		return
	}
	defer file.Close()
	writer:=bufio.NewWriter(file)
	writer.WriteString("lxx is handsome")
	writer.Flush() // 从缓冲区写入硬盘
}

其他

一行行写入到文件

func main() {
	file,err:=os.OpenFile("lxx.txt",os.O_CREATE|os.O_WRONLY,0666)
	if err != nil {
		fmt.Println("打开文件出错:",err)
		return
	}
	defer file.Close()
	d := []string{"Welcome to the world of Go", "Go is a compiled language.", "It is easy to learn Go."}
	for _, v := range d {
		fmt.Fprintln(file, v)
		if err != nil {
			fmt.Println(err)
			return
		}
	}
}

追加到文件

// 只要打开文件:file,err:=os.OpenFile("lxx.txt",os.O_APPEND|os.O_WRONLY,0666)
func main() {
	file,err:=os.OpenFile("lxx.txt",os.O_APPEND|os.O_WRONLY,0666)
	if err != nil {
		fmt.Println("打开文件出错:",err)
		return
	}
	defer file.Close()
	d := []string{"Welcome to the world of Go", "Go is a compiled language.", "It is easy to learn Go."}
	for _, v := range d {
		fmt.Fprintln(file, v)
		if err != nil {
			fmt.Println(err)
			return
		}
	}
}

并发写文件

当多个 goroutines 同时(并发)写文件时,我们会遇到竞争条件(race condition)。因此,当发生同步写的时候需要一个 channel 作为一致写入的条件。

我们将写一个程序,该程序创建 100 个 goroutinues。每个 goroutinue 将并发产生一个随机数,届时将有 100 个随机数产生。这些随机数将被写入到文件里面。我们将用下面的方法解决这个问题 .

  1. 创建一个 channel 用来读和写这个随机数。
  2. 创建 100 个生产者 goroutine。每个 goroutine 将产生随机数并将随机数写入到 channel 里。
  3. 创建一个消费者 goroutine 用来从 channel 读取随机数并将它写入文件。这样的话我们就只有一个 goroutinue 向文件中写数据,从而避免竞争条件。
  4. 一旦完成则关闭文件。

我们开始写产生随机数的 produce 函数:

func produce(data chan int, wg *sync.WaitGroup) {
    n := rand.Intn(999)
    data <- n
    wg.Done()
}

上面的方法产生随机数并且将 data 写入到 channel 中,之后通过调用 waitGroupDone 方法来通知任务已经完成。

让我们看看将数据写到文件的函数:

func consume(data chan int, done chan bool) {
    f, err := os.Create("concurrent")
    if err != nil {
        fmt.Println(err)
        return
    }
    for d := range data {
        _, err = fmt.Fprintln(f, d)
        if err != nil {
            fmt.Println(err)
            f.Close()
            done <- false
            return
        }
    }
    err = f.Close()
    if err != nil {
        fmt.Println(err)
        done <- false
        return
    }
    done <- true
}

这个 consume 的函数创建了一个名为 concurrent 的文件。然后从 channel 中读取随机数并且写到文件中。一旦读取完成并且将随机数写入文件后,通过往 done 这个 cahnnel 中写入 true 来通知任务已完成。

下面我们写 main 函数,并完成这个程序。下面是我提供的完整程序:

package main

import (
	"fmt"
	"math/rand"
	"os"
	"sync"
)

// 生产者,每个生产者随机产生一个999内的数字
func producer(data chan int, wg *sync.WaitGroup) {
	r := rand.Intn(999)
	data <- r
	wg.Done()
}

func consumer(data chan int, done chan bool) {
	file, err := os.Create("concurrent") // 打开一个文件
	if err != nil {
		fmt.Println(err)
		return
	}
	for d := range data {
		_, err := fmt.Fprintln(file, d)
		if err != nil {
			fmt.Println("写入出错")
			file.Close()  // 关闭文件
			done <- false // 成功标志中写入false
			return
		}
	}
	file.Close() // 在for循环外面关闭文件
	done <- true
}
func main() {

	var (
		data = make(chan int)
		done = make(chan bool)
		wg sync.WaitGroup
	)
	// 启动1000个协程生产随机数
	for i := 0; i < 1000; i++ {
		wg.Add(1)
		go producer(data,&wg)
	}
	// 开启消费者,往文件中写随机数
	go consumer(data,done)


	go func() { //在另一个协程中等待所有生产者完成,然后关闭数据信道,不能写在主协程中
		wg.Wait()
		close(data)
	}()
	// 从done中取出数据
	res :=< -done
	if res{ // true表示顺利写完
		fmt.Println("顺利写完")
	}else {// false 表示写出问题
		fmt.Println("写出问题")
	}
}

main 函数创建写入和读取数据的 channel,创建 done 这个 channel,此 channel 用于消费者 goroutinue 完成任务之后通知 main 函数。创建 Waitgroup 的实例 wg,用于等待所有生产随机数的 goroutine 完成任务。

使用 for 循环创建 100 个 goroutines。调用 waitgroup wait() 方法等待所有的 goroutines 完成随机数的生成。然后关闭 channel。当 channel 关闭时,消费者 consume goroutine 已经将所有的随机数写入文件, 将 true 写入 done 这个 channel 中,这个时候 main 函数解除阻塞并且打印 File written successfully

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

go&Python

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值