• 文件基本操作


    读取整个文件

    • 整个文件读取到内存是最基本的文件操作之一。这需要使用ioutil包中的ReadFile函数。
    package main
    
    import (
    	"flag"
    	"fmt"
    	"io/ioutil"
    )
    
    func main() {
    
    	fptr := flag.String("path", "test.txt", "待读取文件的路径")
    	flag.Parse()
    
    	data, err := ioutil.ReadFile(*fptr)
    	if err != nil {
    		fmt.Println(err)
    	}
    	fmt.Println(string(data))
    }
    
    • 以上使用的是运行时指定参数-path=test1.txt来指定读取的文件,也可以使用文件的绝对路径。

    分块读取文件

    • 当文件非常大时,尤其在内存不足的情况下,把整个文件都读入内存是没有意义的。
    • 更好的方法是分块读取文件。这可以使用bufio包来完成。
    • 利用bufio包的'NewReader()'函数实现,其中Read方法可以读取文件内容到缓冲的字节数组中去。
    package main
    
    import (
    	"bufio"
    	"fmt"
    	"io"
    	"os"
    )
    
    func main() {
    
    	// 打开文件
    	f, err := os.Open("test.txt")
    	if err != nil {
    		fmt.Println(err)
    	}
    	// 延迟关闭文件
    	defer func() {
    		if err := f.Close(); err != nil {
    			fmt.Println(err)
    		}
    	}()
    	// 文件读取器
    	r := bufio.NewReader(f)
    	buf := make([]byte, 3) // 便于演示 设置的比较小
    	str := ""
    	for {
    		_, err := r.Read(buf)
    		if err != nil {
    			if err == io.EOF {
    				fmt.Println("文件读取完毕!")
    			} else {
    				fmt.Println(err)
    			}
    			break
    		}
    		fmt.Println(string(buf))
    		str += string(buf)
    	}
    	fmt.Println("完整结果如下:
    ", str)
    }
    

    逐行读取文件

    • 当文件比较大时还可以采用逐行读取的方式实现。
    • 利用bufio包的'NewScanner()'函数实现,其中Scan方法可以判断是否还有下一行,

    Text方法可以获取当前行,Err方法可以获取错误信息。

    package main
    
    import (
    	"bufio"
    	"fmt"
    	"os"
    )
    
    func main() {
    
    	// 打开文件
    	f, err := os.Open("test.txt")
    	if err != nil {
    		fmt.Println(err)
    	}
    	// 延迟关闭文件
    	defer func() {
    		if err := f.Close(); err != nil {
    			fmt.Println(err)
    		}
    	}()
    	// 文件读取器
    	s := bufio.NewScanner(f)
    	str := ""
    	for s.Scan() {
    		fmt.Println(s.Text(), "
    -------分隔符--------")
    		str += s.Text()
    	}
    	if s.Err() != nil {
    		fmt.Println(s.Err().Error())
    	}
    	fmt.Println("完整结果如下:
    ", str)
    }
    

    字符串写入文件

    • 使用 create 创建一个指定名字的文件。

    如果这个文件已经存在,那么 create 函数将截断这个文件。该函数返回一个文件描述符。

    package main
    
    import (
    	"fmt"
    	"os"
    )
    
    func main() {
    
    	f, err := os.Create("123.txt")
    	if err != nil {
    		fmt.Println(err)
    	}
    	defer func() {
    		if err = f.Close(); err != nil {
    			fmt.Println(err)
    		}
    	}()
    
    	_, err = f.WriteString("Hello World!")
    	if err != nil {
    		fmt.Println(err)
    	}
    	fmt.Println("文件写入成功!")
    }
    

    字节写入文件

    • 使用Write方法可以写入字节数组数据。一般为字符对应的UTF-8的10进制编码。
    package main
    
    import (
    	"fmt"
    	"os"
    )
    
    func main() {
    
    	f, err := os.Create("123.txt")
    	if err != nil {
    		fmt.Println(err)
    	}
    
    	defer func() {
    		if err = f.Close(); err != nil {
    			fmt.Println(err)
    		}
    	}()
    
    	bytes := []byte{104, 101, 108, 108, 111, 32, 119, 111, 114, 108, 100}
    	_, err = f.Write(bytes)
    
    	if err != nil {
    		fmt.Println(err)
    	}
    	fmt.Println("文件写入完成")
    }
    

    逐行写入文件

    • 使用fmt.Fprintln函数实现文件的逐行写入。
    package main
    
    import (
    	"fmt"
    	"os"
    )
    
    func main() {
    
    	f, err := os.Create("123.txt")
    	if err != nil {
    		fmt.Println(err)
    	}
    
    	defer func() {
    		if err = f.Close(); err != nil {
    			fmt.Println(err)
    		}
    	}()
    
    	lines := []string{"Hello", "GoLang", "World"}
    
    	for _, v := range lines {
    		_, err = fmt.Fprintln(f, v)
    		if err != nil {
    			fmt.Println(err)
    		}
    	}
    
    	fmt.Println("文件写入完成.")
    }
    

    追加文件内容

    • os.OpenFile(name string, flag int, perm FileMode) (*File, error)函数可以指定文件操作方式。
    package main
    
    import (
    	"fmt"
    	"os"
    )
    
    func main() {
    
    	f, err := os.OpenFile("123.txt", os.O_APPEND|os.O_RDONLY, 0644)
    	if err != nil {
    		fmt.Println(err)
    	}
    
    	defer func() {
    		if err = f.Close(); err != nil {
    			fmt.Println(err)
    		}
    	}()
    
    	lines := []string{"123", "abc", "!@#"}
    
    	for _, v := range lines {
    		_, err = fmt.Fprintln(f, v)
    		if err != nil {
    			fmt.Println(err)
    		}
    	}
    
    	fmt.Println("文件追加写入完成.")
    }
    

    并发写文件

    • 注意文件写入时的竞态条件。
    package main
    
    import (
    	"fmt"
    	"math/rand"
    	"os"
    	"sync"
    )
    
    func main() {
    
    	chNum := make(chan int)
    	chExit := make(chan bool)
    	wg := sync.WaitGroup{}
    
    	// 生产者
    	for i := 0; i < 100; i++ {
    		wg.Add(1)
    		go makeRandom(chNum, &wg)
    	}
    
    	// 消费者
    	go writeFile(chNum, chExit)
    
    	wg.Wait()
    	close(chNum)
    
    	if <-chExit {
    		fmt.Println("文件写入成功.")
    	} else {
    		fmt.Println("文件写入失败.")
    	}
    
    }
    
    func makeRandom(chNum chan int, wg *sync.WaitGroup) {
    
    	chNum <- rand.Intn(1000)
    	wg.Done()
    
    }
    
    func writeFile(chNum chan int, chExit chan bool) {
    
    	f, err := os.Create("123.txt")
    	if err != nil {
    		fmt.Println(err)
    	}
    	defer func() {
    		if err = f.Close(); err != nil {
    			fmt.Println(err)
    		}
    	}()
    
    	for val := range chNum {
    		_, err = fmt.Fprintln(f, val)
    		if err != nil {
    			fmt.Println(err)
    		}
    	}
    
    	chExit <- true
    }
    
  • 相关阅读:
    JAVA8时间插入mysql少了8小时的解决办法
    Kubernetes 部署 Mysql 8.0 数据库(单节点)
    Spring Boot + MyBatisPlus,简直完美!
    美团面试官:生成订单后一段时间不支付订单会自动关闭的功能该如何实现?越详细越好~
    100道Java并发和多线程基础面试题大集合(含解答),这波面试稳了~
    windows端口占用快速查询解决方法
    解决github无法连接错误 OpenSSL SSL_connect: Connection was reset in connection to github.com:443
    Mysql:好好的索引,为什么要下推?
    漫画 | 程序员的悲哀是什么?
    聊聊那些年的骚操作!!!
  • 原文地址:https://www.cnblogs.com/devzyh/p/12670244.html
Copyright © 2020-2023  润新知