Go文件操作

Go文件操作

  • 文件是数据源(保存数据的地方)的一种
  • 输入流与输出流
    • 文件在程序中是以流的形式来操作的
    • 流:数据在数据源(文件)和程序(内存)之间经历的路径
    • 输入流:数据从数据源(文件)到程序(内存)的路径
    • 输出流:数据从程序(内存)到数据源(文件)的路径
  • os.File封装所有文件操作,File是一个结构体

常用文件操作和方法

打开与关闭文件
func Open(name string)(file *File,err error)
  • Open打开一个文件用于读取,如果操作成功,返回的文件对象的方法可用于读取数据;对应的文件描述符具有O_RDONLY模式。如果出错,错误底层类型是*PathError
func (f *File)Close()error
  • Close关闭文件,使文件不能用于读写,其返回可能出现的错误
package main

import (
	"fmt"
	"os"
)

func main(){
	//打开文件
	//file的叫法
	//file对象
	//file指针
	//file文件句柄
	file,err := os.Open("d:/test.txt")
	if err != nil {
		fmt.Println("open file err="err)
	}
	//输出文件,查看文件是声明,文件时一个指针*file
	fmt.Printf("file=%v",file)

	//关闭文件
	err = file.Close()
	if err != nil {
		fmt.Println("close file err=",err)
	}
}

//读取文件的内容并显示在终端(带缓冲方式)
package main

import (
	"bufio"
	"fmt"
	"io"
	"os"
)

func main(){
	//打开文件
	//file的叫法
	//file对象
	//file指针
	//file文件句柄
	file,err := os.Open("d:/test.txt")
	if err != nil {
		fmt.Println("open file err=",err)
	}
	

	//当函数退出时,要及时关闭file,否则会内存泄漏
	defer file.Close()
	
	//创建一个*Reader,是带缓冲的
	/*
	const(
	defaultBufSize = 4096 //默认的缓冲区为4096
	)
	 */
	
	reader := bufio.NewReader(file)
    //NewReader创建一个具有默认大小缓冲、从r读取的*Reader
	//循环读取文件的内容
	for {
		str,err := reader.ReadString('\n')//读到一个换行就结束
		if err == io.EOF {//io.EOF表示文件的末尾
			break
		}
		fmt.Print(str)
	}
	
	fmt.Println("文件读取结束...")
	
}

package main

import (
	"fmt"
	"io/ioutil"
)

//读取文件的内容并显示在终端(使用ioutil一次将整个文件读入内存中)
//适用于文件不大的情况

func main(){
	//使用ioutil.Readfile一次性将文件读取到位
	file := "d:/test.txt"
	content,err := ioutil.ReadFile(file)
	if err != nil {
		fmt.Printf("read file err = %v",err)
	}
	//把读取到的内容显示到终端
	fmt.Printf("%v",content)//[]type输出数字
	fmt.Printf("%v",string(content))
	
	//没有显示的Open文件,因此不需要显示的Close文件
	//文件的Open和Close被封装到ReadFile函数内部


}

创建文件并写入内容
  • 文件打开模式 (可用**|**组合)
const (
	O_RDONLY int = syscall.O_RDONLY//只读模式打开文件
    O_WRONLY int = syscall.O_WRONLY//只写模式打开文件
    O_RDWR int = syscall.O_RDWR//读写模式打开文件
    O_APPEND int = syscall.O_APPEND//写操作时将数据附加到文件尾部
    O_CREATE int = syscall.O_CREAT//如果不存在将创建一个文件
    O_EXCL int = syscall.O_EXCL//和O_CREATE配合使用,文件必须不存在
    O_SYNC int = syscall.O_SYNC//打开文件用于同步I/O
    O_TRUNC int = syscall.O_TRUNC//如果可能,打开时清空文件
)
  • os.OpenFile时是一个更一般性的文件打开函数,会使用指定的选项、指定的模式打开指定名称的文件。如果操作成功,返回文件对象可用于I/O。如果出错,错误底层类型是*PathError
func OpenFile(name string,flag int,perm FileMode)(file *File,err error)
//第二个参数:文件打开模式
//第三个参数:权限控制(linux)
//创建一个新文件,写入内容5局“hello”
package main

import (
	"fmt"
	"bufio"
	"os"
)

func main(){
	//创建一个文件,写入内容
	//打开文件
	filePath := "d:/abc.txt"
	file,err := os.OpenFile(filePath,os.O_WRONLY | os.O_CREATE,0666)
	if err != nil {
		fmt.Printf("open file err = ",err)
		return
	}
	
	//及时关闭file句柄
	defer file.Close()
	//写入内容
	str := "hello"
	//写入时,使用带缓冲的*Writer
	writer := bufio.NewWriter(file)
	for i := 0; i < 5;i++ {
		writer.WriteString(str)
	}
	//因为writer是带缓存的,因此在调用WriterString方法时
	//内容是先写入到缓存区的,所以需要调用Flush方法
	//将缓存数据写入到文件中,否则文件会没有数据
	writer.Flush()
}
判断文件是否存在
  • Golang使用os.Stat()函数返回的错误值进行判断
    • nil:说明文件或文件夹存在
    • 若返回的错误类型使用os.IsNotExist()判断为true,说明文件或文件夹不存在
    • 返回的错误为其他类型,则不确定是否存在
func PathExists(path string)(bool,error) {
    _,err := os.Stat(path)
    if err == nil {
        //文件或目录存在
        return true,nil
    }
    if os.IsNotExist(err){
        return false,nil
    }
    return false,err
}
拷贝文件(视频图片音频)
func Copy(dst Writer,src Reader)(written int64,err error)
//copy函数是由io包提供
package main

import (
	"fmt"
	"os"
	"io"
	"bufio"
)

func CopyFile(dstFileName string,srcFtleName string)(written int64,err error){
	srcFile,err := os.Open(srcFileName)
	if err != nil {
		fmt.Printf("open file err=%v\n",err)
	}
	defer srcFile.Close()
	
	//通过srcFile获取Reader
	reader := bufio.NewReader(srcFile)
	//打开dstFileName
	dstFile,err := os.OpenFile(desFileName,os.O_WRONLY|os.O_CREATE,0666)
	if err != nil {
		fmt.Printf("open file err = %v\n",err)
		return 
	}
	
	//通过dstFile 获取writer
	write := bufio.NewWriter(dstFile)
	defer dstFile.Close()
	
	return io.Copy(writer,reader)
}

func main(){
	srcFile := "d:/flower.jpg"
	dstFile := "e:/abc.jpg"
	_,err := CopyFile(dstFile,srcFile)
	if err != nil {
		fmt.Printf("拷贝完成\n")
	} else {
		fmt.Printf("拷贝错误 err=%v\n",err)
	}
}

命令行参数
  • os.Args是一个string的切片。用于存储所有命令行参数

  • 获取命令行参数

package main

import (
	"fmt"
	"os"
)

func main(){
	fmt.Println("命令行参数有",len(os.Args))
	//遍历os.Args切片,就可以得到所有命令行输入参数值
	for i,v := range os.Args {
		fmt.Printf("Args[%v]=%v\n",i,v)
	}
}
  • flag包用于解析命令行参数
    • 参数顺序可以随意
package main

import (
	"fmt"
	"flag"
)

func main() {
	var user string
	var pwd string
	var host string
	var port int

	//&user就是接受用户命令行中输入的-u后面的参数值
	//“u”就是-u指定参数
	//“”默认值
	//“用户名默认为空”说明
	flag.StringVar(&user,"u","","用户名默认为空")
	flag.StringVar(&pwd,"pwd","","密码默认为空")
	flag.StringVar(&host,"h","localhost","主机名,默认为localhost")
	flag.IntVar(&port,"port","3306","端口号默认为3306")
	
	//转换,必须调用该方法
	fmt.Printf("user=%v pwd=%v host=%v port=%v",user,pwd,host,port)
}
json基本介绍
  • JSON是一种轻量级的数据交换格式,易于人阅读和编写,同时也易于机器解析和生成

  • JSON易于机器解析和生成,并能够有效提升网络传输效率,通常程序在网络传输时会先将数据(结构体、map等)序列化成JSON字符串,到接收方得到JSON字符串时,再反序列化恢复成原来的数据类型(结构体、map等)

  • 在JS语言中,一切都是对象,任何数据类型都可以通过JSON表示

  • JSON键值对是用来保存数据的一种方式

  • {"firstname":"Json"}
    {"name":"tom","age":18,"address":["北京","上海"]}
    [{"name":"tom","age":18,"address":["北京","上海"]},
    {"name":"mary","age":28,"address":["广州","深圳"]}]
    
  • JSON数据在线解析

    • https://www.json.cn/可以验证JSON格式是否正确
JSON序列化
package main

import (
	"encoding/json"
	"fmt"
)

//定义一个结构体
type Monster struct {
	Name string `json:"monster_name"`//反射机制
	Age int `json:"monster_age"`
	Birthday string
	Sal float64
	Skill string
}

func testStruct(){
	monster := Monster{
		Name : "牛魔王",
		Age : 500,
		Birthday : "2011-11-11",
		Sal : 8000.0,
		Skill : "牛魔拳",
	}
	
	//将monster序列化
	data,err := json.Marshal(&monster)
	if err != nil {
		fmt.Printf("序号错误 err=%v\n",err)
	}
	//输出序列后结果
	fmt.Printf("monster序列后=%v\n",string(data))
}

//将map序列化
func testMap(){
	//定义一个map
	var a map[string]interface{}
	//使用map需要make
	a = make(map[string]interface{})
	a["name"] = "红孩儿"
	a["age"] = 30
	a["address"] = "洪崖洞"
	
	//将a这个map进行序列化
	//将monster序列化
	data,err := json.Marshal(a)
	if err != nil {
		fmt.Printf("序列化错误,err=%v\n",err)
	}
	//输出序列化结果
	fmt.Printf("a map 序列化后=%v\n",string(data))
}

//将切片序列化
func testslice(){
	var slice []map[string]interface{}
	var m1 map[string]interface{}
	//使用map前,需要先make
	m1 = make(map[string]interface{})
	m1["name"] = "jack"
	m1["age"] = "7"
	m1["address"] = "北京"
	slice = append(slice,m1)
	
	var m2 map[string]interface{}
	//使用map前需要先make
	m2 = make(map[string]interface{})
	m2["name"] = "tom"
	m2["age"] = "20"
	m2["address"] = [2]string{"墨西哥","夏威夷"}
	slice = append(slice,m2)
	
	//将切片进行序列化操作
	data,err := json.Marshal(slice)
	if err != nil {
		fmt.Printf("序列化失败错误,err=%v\n",err)
	}
	//输出序列化后结果
	fmt.Printf("slice 序列化后=%v\n",string(data))
	
}

func main(){
	testStruct()
	testMap()
	testslice()
	
	//对于结构体的序列化,如果希望序列化后key的名字重新制定
	//可以给struct一个tag标签
}
JSON的反序列化
package main

import (
	"fmt"
	"encoding/json"
)

//定义一个结构体
type Monster struct{
	Name string
	Age int
	Birthday string
	Sal float64
	Skill string
}

//将JSON字符串反序列化成struct
func unmarshalStruct(){
	//说明str在项目开发中,是通过网络传输获取到或者是读取文件获取到
	str := "{\"Name\":\"牛魔王\",\"Age\":500,\"Birthday\":\"2011-11-11\",\"Sal\":8000,\"Skill\":\"牛魔拳\"}"
	
	//定义一个Monster实例
	var monster Monster
	err := json.Unmarshal([]byte(str),&monster)
	if err != nil {
		fmt.Printf("unmarshall err=%v\n",err)
	}
	fmt.Printf("反序列化后monster=%v monster.Name=%v\n",monster,monster.Name)
}

//将JSON字符串反序列化成map
func unmarshalMap(){
	str := "{\"address\":\"洪崖洞\",\"Age\":30,\"name\":\"红孩儿\"}"
	
	//定义一个map
	var a map[string]interface{}
	
	//反序列化不需要make,因为make操作被封装到Unmarshal函数
	err := json.Unmarshal([]byte(str),&a)
	if err != nil {
		fmt.Printf("ummarshal err=%v\n",err)
	}
	fmt.Printf("反序列化后 a=%v\n",a)
}

//将JSON字符串反序列化成切片
func unmarshalSlice(){
	str := "[{\"address\":\"北京\',\"age\":\"7\",\"name\":\"jack\"},"+
		"{\"address\":[\"墨西哥\",\"夏威夷\"],\"age\":\"20\",\"name"\:\"tom\"}]"
	
	//定义一个slice
	var slice []map[string]interface{}
	err := json.Unmarshal([]byte(str),&slice)
	if err != nil {
		fmt.Printf("unmarshal err = %v\n",err)
	}
	fmt.Printf("反序列化后 slice=%v\n",slice)
}

func main(){
	unmarshalMap()
	unmarshalSlice()
	unmarshalStruct()
	
	//在反序列化一个json字符串时,要确保反序列化后的数据类型和原来序列化前的数据类型一致
	//如果json字符串是从程序中获取的,则不需要对"转义处理
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值