zoukankan      html  css  js  c++  java
  • golang读写文件的几种方式

    golang中处理文件有很多种方式,下面我们来看看。

    (1)使用os模块

    先来看看如何查看文件属性

    package main
    
    import (
    	"fmt"
    	"os"
    )
    
    func main() {
    	//打开文件使用os.Open函数,会返回一个文件句柄和一个error
    	file, err := os.Open(`D:komeijisatorisrcday3whiteblum.txt`)
    	if err != nil {
    		fmt.Println("文件打开失败:",err)
    	}
    
    	//调用file.Stat()可以查看文件的信息,这是一个os.FileInfo对象
    	info, err := file.Stat()
    	//属性如下
    	/*
    	type FileInfo interface {
    		Name() string       // 文件名
    		Size() int64        // 文件的大小,按字节计算
    		Mode() FileMode     // 文件的模式
    		ModTime() time.Time // 修改时间
    		IsDir() bool        // 是否是目录
    		Sys() interface{}   // 数据源,一般不用管
    	}
    	 */
    	fmt.Println(info.Name()) // whiteblum.txt
    	fmt.Println(info.Size()) // 183
    
    	//有点类似于linux里面的,第一个-表示文本文件,后面的三个rw-表示可读可写不可执行。
    	//分别是用户、用户所属组、其他组的权限
    	fmt.Println(info.Mode()) // -rw-rw-rw-
    	fmt.Println(info.ModTime()) // 2019-08-31 19:52:44.3146692 +0800 CST
    	fmt.Println(info.IsDir()) // false
    	fmt.Println(info.Sys())  // &{32 {2579124676 30760946} {2579124676 30760946} {2579124676 30760946} 0 183}
    }
    

    读取文件里面的内容

    package main
    
    import (
    	"fmt"
    	"os"
    )
    
    func main() {
    	file, err := os.Open(`D:komeijisatorisrcday3whiteblum.txt`)
    	if err != nil {
    		fmt.Println("文件打开失败:",err)
    	}
    	//忘记说了,文件打开是要关闭的,调用defer函数即可
    	defer file.Close()
    
    	//此外file.Name()还可以拿到文件的所在路径,file.Fd()则是拿到文件的描述符
    	fmt.Println(file.Name()) //D:komeijisatorisrcday3whiteblum.txt
    	fmt.Println(file.Fd()) // 216
    
    	//读取文件内容可以调用file.Read()方法,接收一个字节数组,返回一个int和error
    	buf := make([]byte, 12)
    	//此时文件的内容都会读到buf里面,n则是写入了多少个字节,n不会超过字节数组buf的长度
    	n, err := file.Read(buf)
    	
    	//将写入的内容读取出来
    	fmt.Println(string(buf[:n])) //白色相簿
    }
    

    我们注意到:当前只是读取了12个字节,并没有全部读取完。这是因为我们的buf长度只有12,我们可以将容量变得更大一些,但是到底要弄多大呢?这是一个未知数。弄小了一次读不完,要是弄大了,会浪费。因此最好的办法,不要一次就读完,而是循环读取,这样不就好了吗?一般的话,我们都将buf的长度设置为1024个字节,但由于我的文件比较小,所以就设置为12个字节

    package main
    
    import (
    	"fmt"
    	"io"
    	"os"
    )
    
    func main() {
    	file, err := os.Open(`D:komeijisatorisrcday3whiteblum.txt`)
    	if err != nil {
    		fmt.Println("文件打开失败:",err)
    	}
    	defer file.Close()
    
    	buf := make([]byte, 12) // 存放文件内容的缓存,相当于中转站
    	data := make([]byte, 0) // 用来存放文件内容,buf读取的内容都会写到data里面去
    
    	for {
    		//无限循环,不断读取
    		n, err := file.Read(buf)
    		// 什么时候文件读完呢?如果文件读完的话,那么err不为nil,而是io.EOF
    		// 所以我们可以进行判断
    		if err != nil {
    			//如果err != nil说明出错了,但如果还等于io.EOF的话,说明读完了,因为文件读完,err也不为nil。直接break
    			if err == io.EOF{
    				break
    			} else {
    				//如果错误不是io.EOF的话,说明就真的在读取中出现了错误,直接panic出来
    				panic(err)
    			}
    		}
    		//此时文件内容写到buf里面去了,写了多少个呢?写了n个,那么我们再写到data里面去
    		data = append(data, buf[: n]...)
    
    		//我们来打印一下,每次写了多少个字节
    		fmt.Printf("写入%d个字节
    ", n)
    		/*
    		写入12个字节
    		写入12个字节
    		写入12个字节
    		写入12个字节
    		写入12个字节
    		写入12个字节
    		写入12个字节
    		写入12个字节
    		写入12个字节
    		写入12个字节
    		写入12个字节
    		写入12个字节
    		写入12个字节
    		写入12个字节
    		写入12个字节
    		写入6个字节
    		 */
    	}
    
    	//写完之后,我们来打印一下
    	fmt.Println(string(data))
    	/*
    	白色相簿什么的,已经无所谓了。
    	因为已经不再有歌,值得去唱了。
    	传达不了的恋情,已经不需要了。
    	因为已经不再有人,值得去爱了。
    	*/
    }
    

    那么如何使用os模块来写入文件呢?

    package main
    
    import (
    	"fmt"
    	"os"
    )
    
    func main() {
    	//既然要写,那么就不能使用Open了,而是使用Create
    	//Create会创建一个文件,如果存在会清空原有的内容
    	file, err := os.Create(`D:komeijisatorisrcday3whiteblum.txt`)
    	if err != nil {
    		fmt.Println("文件创建失败:",err)
    	}
    	defer file.Close()
    	//写入文件可以调用file.WriteString,或者file.Write方法
    	//前者是写入字符,后者是写入字节。
    	// 其实WriteString底层是将我们传入的字符串变成字节数组,然后还是调用Write方法
    	//会有两个返回值,一个是我们写入的个数,一个是error
    	n, err := file.WriteString("这是新写入的内容,原来的内容会丢失")
    	//golang是按照字节算的,一个汉字占三个字节
    	fmt.Println(n) // 51
    
    	//再来读取一下看看,有没有写入
    	file, err = os.Open(`D:komeijisatorisrcday3whiteblum.txt`)
    	//直接将数组设置的大一些,一次读取完毕
    	new_buf := make([]byte, 1024)
    	n, _ = file.Read(new_buf)
    	fmt.Println(string(new_buf[: n])) // 这是新写入的内容,原来的内容会丢失
    }
    

    其实无论是Open还是Create,底层都是调用了OpenFile

    package main
    
    import (
    	"fmt"
    	"os"
    )
    
    func main() {
    	// OpenFile接收三个参数
    	// 1.文件名
    	// 2.文件的模式,支持如下
    	/*
    	os.O_RDONLY: 以只读的方式打开
    	os.O_WRONLY: 以只写的方式打开
    	os.O_RDWR : 以读写的方式打开
    	os.O_NONBLOCK: 打开时不阻塞
    	os.O_APPEND: 以追加的方式打开
    	os.O_CREAT: 创建并打开一个新文件
    	os.O_TRUNC: 打开一个文件并截断它的长度为零(必须有写权限)
    	os.O_EXCL: 如果指定的文件存在,返回错误
    	os.O_SHLOCK: 自动获取共享锁
    	os.O_EXLOCK: 自动获取独立锁
    	os.O_DIRECT: 消除或减少缓存效果
    	os.O_FSYNC : 同步写入
    	os.O_NOFOLLOW: 不追踪软链接
    	 */
    	// 3.权限,一般设置为0666,这在linux下有用,Windows下面没太大卵用
    
    	// 以只写的方式打开,并且写入的时候,是以追加的形式写入
    	file, _ := os.OpenFile(`D:komeijisatorisrcday3whiteblum.txt`,os.O_WRONLY|os.O_APPEND, 0666)
    
    	_, _ = file.Write([]byte("
    这是新的内容,但是原来的内容还在"))
    
    	//写入之后,我们再以只读方式打开
    	file, _ = os.OpenFile(`D:komeijisatorisrcday3whiteblum.txt`,os.O_RDONLY, 0666)
    	buf := make([]byte, 1024)
    	n, _ := file.Read(buf)
    	fmt.Println(string(buf[: n]))
    	/*
    	这是新写入的内容,原来的内容会丢失
    	这是新的内容,但是原来的内容还在
    	 */
    }
    

    但是通常我们直接使用Open和Create函数

    (2)使用bufio

    bufio相当于是在os.OpenFile得到的文件句柄之上进行一层封装,bufio,从名字上也能看出来是带缓存的io。

    package main
    
    import (
    	"bufio"
    	"fmt"
    	"io"
    	"os"
    )
    
    func main() {
    	file, _ := os.Open(`D:komeijisatorisrcday3whiteblum.txt`)
    
    	//使用bufio.NewReader进行一层包装
    	reader := bufio.NewReader(file)
    	//首先这个reader,可以像file一样,使用Read方法
    	//然而reader还可是按照指定字符来读,比如我想一行一行读,就可以指定换行符来读
    	for{
    		//返回string和error
    		s, err := reader.ReadString('
    ') //表示每读到
    就停止
    		//这里使用print,因为文件本身有换行符,println自带换行,所以使用print
    		fmt.Print("读取一行:", s)
    		/*
    		读取一行:白色相簿什么的,已经无所谓了。
    		读取一行:因为已经不再有歌,值得去唱了。
    		读取一行:传达不了的恋情,已经不需要了。
    		读取一行:因为已经不再有人,值得去爱了。
    		 */
    		if err != nil {
    			if err == io.EOF{
    				break
    			} else {
    				panic(err)
    			}
    		}
    	}
    }
    
    package main
    
    import (
    	"bufio"
    	"bytes"
    	"fmt"
    	"os"
    )
    
    func main() {
    	file, _ := os.Open(`D:komeijisatorisrcday3whiteblum.txt`)
    
    	//除了NewReader,还有一个NewScanner
    	scanner := bufio.NewScanner(file)
    	for scanner.Scan(){
    		//可以看到我们使用println打印,行与行之间没有空隙,说明scanner.Text()没有把换行符读进去。
    		fmt.Println(scanner.Text())
    		/*
    		白色相簿什么的,已经无所谓了。
    		因为已经不再有歌,值得去唱了。
    		传达不了的恋情,已经不需要了。
    		因为已经不再有人,值得去爱了。
    		 */
    	}
    
    	//但是这都是一行一行读的,我们可以写到缓存里面去
    	//这个缓存使用bytes.Buffer{}来创建
    	buf := bytes.Buffer{}
    	file, _ = os.Open(`D:komeijisatorisrcday3whiteblum.txt`)
    	scanner = bufio.NewScanner(file)
    	for scanner.Scan(){
    		//直接调用buf.WriteString即可
    		buf.WriteString(scanner.Text())
    		// 当然还可以使用buf.Write写入字节,同时也可以使用scanner.Bytes()得到字节。buf.Write(scanner.Bytes())
    	}
    	//可以调用buf.Bytes()拿到字节
    	//也可以调用buf.String()拿到String
    	fmt.Println(buf.String())  // 白色相簿什么的,已经无所谓了。因为已经不再有歌,值得去唱了。传达不了的恋情,已经不需要了。因为已经不再有人,值得去爱了。
    	//因为没有读取换行符,所以是连在一起的
    
    	//这里再提一下bytes.Buffer{},这是一个非常方便的字节缓存。用来组合字符串非常方便
    	buffer := bytes.Buffer{}
    	buffer.WriteString("哈哈")
    	buffer.WriteString("呱呱")
    	buffer.Write([]byte("嘻嘻"))
    	fmt.Println(buffer.String())  // 哈哈呱呱嘻嘻
    	fmt.Println(buffer.Bytes()) // [229 147 136 229 147 136 229 145 177 229 145 177 229 152 187 229 152 187]
    
    	//当然buffer也有ReadString,和Read方法
    	s, _ := buffer.ReadString('
    ')
    	fmt.Println(s) // 哈哈呱呱嘻嘻
    
    	buffer.WriteString("你胸大,你先说")
    	b := make([]byte, 1024)
    	n, _  := buffer.Read(b)
    	fmt.Println(string(b[: n])) // 你胸大,你先说
    }
    

    (3)使用ioutil模块

    ioutil是一个非常强大模块

    package main
    
    import (
    	"fmt"
    	"io/ioutil"
    	"os"
    )
    
    func main() {
    	file, _ := os.Open(`D:komeijisatorisrcday3whiteblum.txt`)
    	// 直接将file丢进去,可以读取全部内容
    	s, _ := ioutil.ReadAll(file)
    	fmt.Println(string(s))
    	/*
    	白色相簿什么的,已经无所谓了。
    	因为已经不再有歌,值得去唱了。
    	传达不了的恋情,已经不需要了。
    	因为已经不再有人,值得去爱了。
    	 */
    	// 是不是很方便呢?其实还有更方便的
    	//调用ReadFile,传入文件名直接得到字节数组和error。当然底层是使用了os.Open和ioutil.ReadAll
    	s, _ = ioutil.ReadFile(`D:komeijisatorisrcday3whiteblum.txt`)
    	fmt.Println(string(s))
    	/*
    	白色相簿什么的,已经无所谓了。
    	因为已经不再有歌,值得去唱了。
    	传达不了的恋情,已经不需要了。
    	因为已经不再有人,值得去爱了。
    	 */
    }
    

    当然ioutil开可以写入文件

    package main
    
    import (
    	"bytes"
    	"fmt"
    	"io/ioutil"
    )
    
    func main() {
    	buf := bytes.Buffer{}
    	buf.WriteString("明明是我先来的
    ")
    	buf.WriteString("为什么会变成这样呢
    ")
    	buf.WriteString("何でそんなに慣れてんだよ
    ")
    	buf.WriteString("雪菜と何度もキースしたんだよ")
    	//传入filename,content,权限
    	_ = ioutil.WriteFile(`D:komeijisatorisrcday3whiteblum.txt`, buf.Bytes(), 0666)
    
    	//读取出来看看
    	s, _ := ioutil.ReadFile(`D:komeijisatorisrcday3whiteblum.txt`)
    	fmt.Println(string(s))
    	/*
    	明明是我先来的
    	为什么会变成这样呢
    	何でそんなに慣れてんだよ
    	雪菜と何度もキースしたんだよ
    	 */
    }
    

    之前说ioutil很强大,是因为还有别的用处,比如读取目录

    package main
    
    import (
    	"fmt"
    	"io/ioutil"
    )
    
    func main() {
    	files, _ := ioutil.ReadDir(`C:python37Libsite-packages	ornado`)
    	//返回一个[]os.FileInfo和error
    	for _, file := range files{
    		if !file.IsDir(){
    			fmt.Println(file.Name())
    			/*
    			__init__.py
    			_locale_data.py
    			auth.py
    			autoreload.py
    			concurrent.py
    			curl_httpclient.py
    			escape.py
    			gen.py
    			http1connection.py
    			httpclient.py
    			httpserver.py
    			httputil.py
    			ioloop.py
    			iostream.py
    			locale.py
    			locks.py
    			log.py
    			netutil.py
    			options.py
    			process.py
    			py.typed
    			queues.py
    			routing.py
    			simple_httpclient.py
    			speedups.cp37-win_amd64.pyd
    			tcpclient.py
    			tcpserver.py
    			template.py
    			testing.py
    			util.py
    			web.py
    			websocket.py
    			wsgi.py
    			 */
    		}
    	}
    }
    
  • 相关阅读:
    第10组 Beta冲刺 (3/5)
    第10组 Beta冲刺 (2/5)
    第10组 Beta冲刺 (1/5)
    第10组 Alpha冲刺 (3/6)
    第10组 Alpha冲刺 (2/6)
    第10组 Alpha冲刺 (1/6)
    第一次作业
    第二次作业
    机器学习_第一次个人作业
    软工实践个人总结
  • 原文地址:https://www.cnblogs.com/traditional/p/11440728.html
Copyright © 2011-2022 走看看