GO 利用bufio包(流式操作) - 并发写文件/读文件示例

并发写文件:

注意点:

  • runtime.GOMAXPROCS(runtime.NumCPU()) 限制并发写操作的协程数:
    协程数不宜过多,避免协程间的频繁切换影响性能(根据cpu核数而定)
  • WriteString()操作要加锁,否则最终写入数据有问题(乱码等...)
  • 最后记得Flush()一下:
    bufio 通过 flush 操作将缓冲写入真实的文件的,所以一定要在关闭文件之前先flush,否则会造成数据丢失的情况
package mainimport ("bufio""fmt""os""runtime""runtime/debug""sync"
)// bufio库的流式处理	如果文件较小,使用ioutil也不失为一种方法
func WriteDataToTxt() {txtFile, err := os.OpenFile("55555.txt", os.O_CREATE|os.O_RDWR|os.O_TRUNC, 0777) // O_TRUNC 清空重写if err != nil {fmt.Println("WriteDataToTxt os.OpenFile() err:", err)return}defer txtFile.Close()// txtFile.WriteString() // os操作文件-效率低bufWriter := bufio.NewWriter(txtFile)var wg sync.WaitGrouplimitChan := make(chan struct{}, runtime.GOMAXPROCS(runtime.NumCPU())) // 最大并发协程数var mutex sync.Mutexfor i := 0; i < 10000; i++ { // 写1w行测试limitChan <- struct{}{}wg.Add(1)go func(j int) {defer func() {if e := recover(); e != nil {fmt.Printf("WriteDataToTxt panic: %v,stack: %s\n", e, debug.Stack())// return}wg.Done()<-limitChan}()// 模拟业务逻辑:先整合所有数据,然后再统一写WriteString()strId := fmt.Sprintf("%v", j)strName := fmt.Sprintf(" user_%v", j)strScore := fmt.Sprintf(" %d", j*10)mutex.Lock() // 要加锁/解锁,否则 bufWriter.WriteString 写入数据有问题_, err := bufWriter.WriteString(strId + strName + strScore + "\n")if err != nil {fmt.Printf("WriteDataToTxt WriteString err: %v\n", err)return}mutex.Unlock()// bufWriter.Flush() // 刷入磁盘(错误示例:WriteDataToTxt err: short write,short write;因为循环太快,有时写入的数据量太小了)}(i)}wg.Wait()bufWriter.Flush() // 刷入磁盘(正确示例,bufio 通过 flush 操作将缓冲写入真实的文件的,所以一定要在关闭文件之前先flush,否则会造成数据丢失的情况)
}

报错: 

读文件:

注意点:

  • 读取文件中一行内容时,ReadSliceReadLine性能优于ReadBytesReadString,但由于ReadLine对换行的处理更加全面(兼容\n\r\n换行),因此,实际开发过程中,建议使用ReadLine函数。
  • 关于os.File、bufio、ioutil 写文件的性能比较,参考:

    https://segmentfault.com/a/1190000023691973

package mainimport ("bufio""fmt""io""os"
)// 读文件
func ReadDataFromTxt() {txtFile, err := os.OpenFile("55555.txt", os.O_RDONLY, 0777) // O_TRUNC 清空重写if err != nil {fmt.Println("WriteDataToTxt os.OpenFile() err:", err)return}defer txtFile.Close()bufReader := bufio.NewReader(txtFile)for {data, _, err := bufReader.ReadLine() // 读一行日志if err == io.EOF {                   // 如果列表读完了,退出fmt.Println("数据读完了~")break}fmt.Println("data: ", string(data))}return
}


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部