当前位置: 首页 > article >正文

【Goalng】第九弹-----文件操作、JSON处理

 🎁个人主页星云爱编程

 🔍所属专栏:【Go】 

🎉欢迎大家点赞👍评论📝收藏⭐文章

 长风破浪会有时,直挂云帆济沧海

目录

1.文件操作

1.1文件介绍

1.2.文件流

1.3.打开和关闭文件

1.4.读文件操作

1.5.写文件操作

1.6判断文件是否存在

1.7拷贝文件

2.flag解析命令行参数

2.1.命令行参数基本使用

2.2flag包解析命令行参数

 2.3flag包处理命令行参数

3.json处理

3.1JSON介绍

3.2Json数据格式说明

3.3JSON序列化

3.4JSON反序列化

结语


1.文件操作

1.1文件介绍

文件是保存数据的地方,例如word文档、txt文本文件,excel文件等都是文件。文件能保存图片,视屏,音频等。

1.2.文件流

文件在程序中是以的形式来操作的:

:数据在数据源(文件)和程序(内存)之间经历的路程。

输入流:数据从数据源(文件)到程序(内存)的路径。

输出流:数据从程序(内存)到数据源(文件)的路径。 

1.3.打开和关闭文件

打开文件用到的方法:

(1)默认文件模式:

(2) 可指定文件模式:

 其flag可为的常量:

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  // 如果可能,打开时清空文件
)

 关闭文件用到的方法:

使用案例:

package main
import (
	"fmt"
	"os"
)

func main(){
	//文件路径
	path:="D:/goProject/src/basic/io/main/text/a.txt"
	//打开文件
	file ,err:=os.Open(path)
	if err!=nil{//打开失败
		fmt.Printf("open err:%v\n",err)
	}
	//输出文件,看看会输出什么?
	fmt.Printf("%v",file)//&{0xc00008c6c8}
	err=file.Close()
	if err!=nil{//关闭失败
		fmt.Printf("close err:%v\n",err)
	}
}

说明:

  • Open方法和Close方法都在os包下,使用时要导入os包
  • file就是个指针

1.4.读文件操作

(1)带缓冲读文件

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

func main(){
	path:="D:/goProject/src/basic/io/main/text/a.txt"
	file ,err:=os.Open(path)
	if err!=nil{//打开失败
		fmt.Printf("open err:%v\n",err)
	}
	defer file.Close()

	// 创建一个 *Reader,是带缓冲的
	/*
	const(
	 	defaultBufsize= 4096 //默认的缓冲区为4096
	)
	 */
	readr:=bufio.NewReader(file)
	//循环的读取文件的内容
	for{
		str,err:=readr.ReadString('\n')//读取到\n就结束,即一行一行的读
		if err==io.EOF{//io.EOF表示文件的末尾
			break
		}
		//输出内容
		fmt.Print(str)
	}
	fmt.Println("\n文件读取结束")
}

(2)一次性读文件

案例:

package main
import(
	"fmt"
	"io/ioutil"
)

func main(){
	//文件路径
	path:="D:/goProject/src/basic/io/main/text/a.txt"
	//一次性读取文件
	content,err:=ioutil.ReadFile(path)
	if err!=nil{
		fmt.Println("read err:",err)
	}
	// fmt.Println(content) 此时输出的是byte[],得用string转化才能输出原内容 
	fmt.Println(string(content))
	//我们没有显式的open文件,因此也不需要显式的close文件
	//因为,文件的open和close被封装到 ReadFile 函数内部
}

1.5.写文件操作

(1)创建新文件并写入数据

package main
import (
	"fmt"
	"os"
	"bufio"
)

func main(){
	//文件路径
	path:="D:/goProject/src/basic/io/main/text/b.txt"
	//打开文件
	file,err:=os.OpenFile(path,os.O_WRONLY | os.O_CREATE,0666)
	if err!=nil{
		fmt.Println("open err:",err)
		return
	}
	//最后关闭file文件
	defer file.Close()
	//写入内容
	str:="好好学习,天天向上"
	//用带缓存的*writer写入
	writer:=bufio.NewWriter(file)
	for i:=0;i<5;i++{
		writer.WriteString(str)
		writer.WriteString("\n")  // 添加换行
	}
	//因为writer是带缓存的,因此在调用WriteString时
	//是先将内容写入到缓存中,所以需要用Flush方法
	//将缓存的数据真正的写入到文件中,否则文件中会没有数据
	writer.Flush()
	fmt.Println("写入完成")
}

(2)打开原有文件,将原内容覆盖写入

package main
import (
	"fmt"
	"os"
	"bufio"
)

func main(){
	//文件路径
	path:="D:/goProject/src/basic/io/main/text/b.txt"
	//打开原有文件
	file,err:=os.OpenFile(path,os.O_WRONLY | os.O_TRUNC,0666)
	if err!=nil{
		fmt.Println("open err:",err)
		return
	}
	//最后关闭file文件
	defer file.Close()
	//写入内容
	str:="温故而知新,可以为师矣"
	//用带缓存的*writer写入
	writer:=bufio.NewWriter(file)
	for i:=0;i<5;i++{
		writer.WriteString(str)  
		writer.WriteString("\n")  // 添加换行
	}
	//因为writer是带缓存的,因此在调用WriteString时
	//是先将内容写入到缓存中,所以需要用Flush方法
	//将缓存的数据真正的写入到文件中,否则文件中会没有数据
	writer.Flush()
	fmt.Println("写入完成")
}

 (3)打开原有文件,在原文件上追加写入

package main
import (
	"fmt"
	"os"
	"bufio"
)

func main(){
	//文件路径
	path:="D:/goProject/src/basic/io/main/text/b.txt"
	//打开原有文件
	file,err:=os.OpenFile(path,os.O_WRONLY | os.O_APPEND,0666)
	if err!=nil{
		fmt.Println("open err:",err)
		return
	}
	//最后关闭file文件
	defer file.Close()
	//写入内容
	str:="实迷途其未远,觉今是而昨非"
	//用带缓存的*writer写入
	writer:=bufio.NewWriter(file)
	for i:=0;i<5;i++{
		writer.WriteString(str)  
		writer.WriteString("\n")  // 添加换行
	}
	//因为writer是带缓存的,因此在调用WriteString时
	//是先将内容写入到缓存中,所以需要用Flush方法
	//将缓存的数据真正的写入到文件中,否则文件中会没有数据
	writer.Flush()
	fmt.Println("写入完成")
}

 (4)打开原有文件,并进行读和写操作

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

func main(){
	//文件路径
	path:="D:/goProject/src/basic/io/main/text/b.txt"
	//打开原有文件
	file,err:=os.OpenFile(path,os.O_RDWR | os.O_APPEND,0666)
	if err!=nil{
		fmt.Println("open err:",err)
		return
	}
	//最后关闭file文件
	defer file.Close()
	//读操作
	reader:=bufio.NewReader(file)
	for{
		str1,err:=reader.ReadString('\n')
		if err==io.EOF{
			break
		}
		fmt.Print(str1)
	}

	//写操作
	//写入内容
	str:="故有之以为用,无之以为利"
	//用带缓存的*writer写入
	writer:=bufio.NewWriter(file)
	for i:=0;i<5;i++{
		writer.WriteString(str)  
		writer.WriteString("\n")  // 添加换行
	}
	//因为writer是带缓存的,因此在调用WriteString时
	//是先将内容写入到缓存中,所以需要用Flush方法
	//将缓存的数据真正的写入到文件中,否则文件中会没有数据
	writer.Flush()
	fmt.Println("写入完成")
}

1.6判断文件是否存在

golang判断文件或文件夹是否存在的方法为使用os.Stat()函数返回的错误值进行判断:

  • 如果返回的错误为nil,说明文件或文件夹存在
  • 如果返回的错误类型使用os.IsNotExist()判断为true,说明文件或文件夹不存在
  • 如果返回的错误为其它类型,则不确定是否在存在
package main
import (
	"fmt"
	"os"
	"bufio"
)

func main(){
	//文件路径
	path:="D:/goProject/src/basic/io/main/text/b.txt"
	
	// 检查文件是否存在
	if _, err := os.Stat(path); os.IsNotExist(err) {
		fmt.Println("文件不存在,将创建新文件")
	} else if err != nil {
		fmt.Println("检查文件出错:", err)
		return
	} else {
		fmt.Println("文件已存在,将追加内容")
	}
}

1.7拷贝文件

package main
import (
	"fmt"
	"os"
	"io"
)

func CopyFile(srcPath, destPath string)(written int64, err error){
	// 打开源文件
	src, err := os.Open(srcPath)
	if err != nil{
		return 0, fmt.Errorf("打开源文件错误: %v", err)
	}
	defer src.Close()

	// 创建目标文件
	dest, err := os.Create(destPath)
	if err != nil{
		return 0, fmt.Errorf("创建目标文件错误: %v", err)
	}
	defer dest.Close()

	// 复制文件内容
	return io.Copy(dest, src)
}

func main(){
	srcPath := "D:\\goProject\\src\\basic\\io\\main\\c.jpg"
	destPath := "D:\\goProject\\src\\basic\\io\\main\\text\\copy.jpg"
	
	written, err := CopyFile(srcPath, destPath)
	if err != nil {
		fmt.Println("复制失败:", err)
		return
	}
	fmt.Printf("成功复制 %d 字节\n", written)
}

2.flag解析命令行参数

2.1.命令行参数基本使用

package main
import (
	"fmt"
	"os"
)

func main(){
	fmt.Println("命令行参数有",len(os.Args))
	//遍历命令行参数
	for i,v:=range os.Args{
		fmt.Printf("args[%v]=%v\n",i,v)
	}

}

2.2flag包解析命令行参数

前面的方式是比较原生的方式,对解析参数不是特别的方便,特别是带有指定参数形式的命令行;

Go提供了flag包,可以方便的解析命令行参数,并且参数顺序可以随意

package main
import(
	"fmt"
	"flag"
)

func main(){
	//定义几个变量,用于接受命令行的参数值
	var user string
	var pwd string
	var host string
	var port int
	//此例子用于mysql的连接
	/*
	func (f *FlagSet) StringVar(p *string, name string, value string, usage string)
	String用指定的名称、默认值、使用信息注册一个string类型flag。返回一个保存了该flag的值的指针。
	*/
	// u就是-u指定参数
	// ""为-u指定参数的默认值
	//"用户名,默认为空"  -说明
	flag.StringVar(&user,"u","","用户名,默认为空")
	flag.StringVar(&pwd,"pwd","","密码,默认为空")
	flag.StringVar(&host,"h","localhost","主机名,默认为localhost")
	flag.IntVar(&port,"port",3306,"端口号,默认为3306")
	//这里有一个非常重要的操作,转换,必须调用该方法
	flag.Parse()
	//输出结果
	fmt.Printf(" user=%v\n pwd=%v\n host=%v\n port=%v\n",user,pwd,host,port)
}

 2.3flag包处理命令行参数

package main

import (
	"flag"
	"fmt"
)

func main() {
	// 定义命令行参数
	name := flag.String("name", "Guest", "用户姓名")
	age := flag.Int("age", 18, "用户年龄")
	verbose := flag.Bool("v", false, "是否显示详细信息")

	// 解析命令行参数
	flag.Parse()

	// 使用解析后的参数
	fmt.Printf("姓名: %s\n", *name)
	fmt.Printf("年龄: %d\n", *age)
	if *verbose {
		fmt.Println("显示详细信息")
	}
}

说明:

(1)定义参数:

  •  flag.String() :定义字符串类型参数
  • flag.Int() :定义整数类型参数
  • flag.Bool() :定义布尔类型参数

(2)参数解析

  • flag.Parse() :解析命令行参数

(3)使用参数

  • 通过 * 解引用获取参数值

3.json处理

3.1JSON介绍

JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,易于人阅读和编写,同时也易于机器解析和生成

JSON是在2001年开始推广使用的数据格式,目前已经成为主流的数据格式。

JSON易于机器解析和生成,并有效地提升网络传输效率,通常程序在网络传输时会先将数据(结构体、map等)序列化成json字符串,到接收方得到json字符串时,在反序列化恢复成原来的数据类型(结构体、map等)。这种方式已然成为各个语言的标准。

3.2Json数据格式说明

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

JSON键值对是用来保存数据的一种方式,键值对组合中的键名写在前面并用双引号""包裹,使用冒号:分隔,然后紧接着值

基本结构:

(1)对象:用 {} 表示,包含键值对

{
  "name": "Alice",
  "age": 25
}

(2)数组:用 [] 表示,包含多个值 

["apple", "banana", "orange"]

(3)值 :可以是字符串、数字、布尔值、null、对象或数组

 JSON在线解析: JSON在线解析

3.3JSON序列化

JSON序列化是将对应的数据结构(例如struct,map,slice)转换为JSON格式字符串的过程。

案例:

package main
import(
	"fmt"
	"encoding/json"
)

type Stu struct{
	Name string
	Age int
	Gender string
	Score  float64
	Phone string
}
//将结构体序列化
func testStruct(){
	stu:=Stu{
		Name:"jack",
		Age: 12,
		Gender: "男",
		Score:85.6,
		Phone:"1581689988",
	}
	//将stu序列化
	data,err:=json.Marshal(&stu)
	if err!=nil{
		panic(err)
	}
	//输出序列化后的结果
	fmt.Println(string(data))
	//{"Name":"jack","Age":12,"Gender":"男","Score":85.6,"Phone":"1581689988"}
}

//将map序列化
func testMap(){
	//定义一个map
	var a map[string]interface{}
	//使用map前,需要make
	a = make(map[string]interface{})
	a["name"]="李星云"
	a["age"]=21
	a["skill"]="九幽玄天神功"
	a["lover"]="姬如雪"
	a["address"]="长安"

	//将a序列化
	data,err:=json.Marshal(a)
	if err!=nil{
		panic(err)
	}
	//输出序列化的结果
	fmt.Println(string(data))
	//{"address":"长安","age":21,"lover":"姬如雪","name":"李星云","skill":"九幽玄天神功"}

}

//对切片序列化
func testSlice(){
	var slice []map[string]interface{}

	var a map[string]interface{}
	//使用map前,需要make
	a = make(map[string]interface{})
	a["name"]="李星云"
	a["age"]=21
	a["skill"]="九幽玄天神功"
	a["lover"]="姬如雪"
	a["address"]="长安"

	var b map[string]interface{}
	//使用map前,需要make
	b = make(map[string]interface{})
	b["name"]="姬如雪"
	b["age"]=19
	b["skill"]="幻音诀"
	b["lover"]="李星云"
	b["address"]="幻音坊"
	//将a,b添加到slice中
	slice=append(slice,a)
	slice=append(slice,b)

	//将切片进行序列化操作
	data,err:=json.Marshal(slice)
	if err!=nil{
		panic(err)
	}
	//输出序列化结果
	fmt.Println(string(data))
	//[{"address":"长安","age":21,"lover":"姬如雪","name":"李星云","skill":"九幽玄天神功"},{"address":"幻音坊","age":19,"lover":"李星云","name":"姬如雪","skill":"幻音诀"}]
}

//对基本数据类型进行序列化
//对基本数据类型进行序列化意义不大
func testFloat64(){
	var num float64=3.1415926535
	//对num进行序列化
	data,err:=json.Marshal(num)
	if err!=nil{
		panic(err)
	}
	//输出序列化后的结果
	fmt.Println(string(data))
}

func main(){
	testStruct()
	testMap()
	testSlice()
	testFloat64()
}

注意事项:

  • 结构体字段首字母必须大写,否则无法被序列化
  • 若想让序列化后的结构体字段首字母小写,可以使用tag标签
  • 可以使用 json:",omitempty" 标签来忽略空值字段
  • 可以使用 json:"-" 标签来忽略某个字段

3.4JSON反序列化

JSON反序列化是将JSON格式字符串转换为对应的数据结构(例如struct,map,slice)的过程

package main
import(
	"fmt"
	"encoding/json"
)

type Stu struct{
	Name string
	Age int
	Gender string
	Score  float64
	Phone string
}

//演示将json字符串,反序列化为struct
func unmarshalStruct(){
	str:="{\"Name\":\"jack\",\"Age\":12,\"Gender\":\"男\",\"Score\":85.6,\"Phone\":\"1581689988\"}"

	//定义一个Stu实例
	var stu Stu
	err:=json.Unmarshal([]byte(str),&stu)
	if err!=nil{
		panic(err)
	}
	//输出反序列化后的str
	fmt.Println(stu)
}

//演示将json字符串,反序列化为map
func unmarshalMap(){
	str:=`{"address":"长安","age":21,"lover":"姬如雪","name":"李星云","skill":"九幽玄天神功"}`
	
	//定义一个map实例
	var a map[string]interface{}
	err:=json.Unmarshal([]byte(str),&a)
	if err!=nil{
		panic(err)
	}
	//输出反序列化后的str
	fmt.Println(a)
}

//演示将json字符串,反序列化为slice
func unmarshalSlice(){
	str:=`[{"address":"长安","age":21,"lover":"姬如雪","name":"李星云","skill":"九幽玄天神功"},{"address":"幻音坊","age":19,"lover":"李星云","name":"姬如雪","skill":"幻音诀"}]`
	
	//定义一个slice实例
	var slice []map[string]interface{}
	//进行反序列化
	err:=json.Unmarshal([]byte(str),&slice)
	if err!=nil{
		panic(err)
	}
	//输出反序列化后的结果
	fmt.Println(slice)
}

func main(){
	unmarshalStruct()
	unmarshalMap()
	unmarshalSlice()
}

说明:

(1)在反序列化一个json字符串时,要确保反序列化后的数据类型和原来序列化前的数据类型一致。

(2)如果json字符串是通过程序获取到的,则不需要再对"进行转义处理

结语

感谢您的耐心阅读,希望这篇博客能够为您带来新的视角和启发。如果您觉得内容有价值,不妨动动手指,给个赞👍,让更多的朋友看到。同时,点击关注🔔,不错过我们的每一次精彩分享。若想随时回顾这些知识点,别忘了收藏⭐,让知识触手可及。您的支持是我们前进的动力,期待与您在下一次分享中相遇!


http://www.kler.cn/a/614837.html

相关文章:

  • Linux Mem -- Slub内存分配器的几点疑问及解答
  • 【设计模式】抽象工厂模式(含与工厂方法模式的对比)
  • 智绅科技:AI赋能智慧养老,打造长者品质生活
  • 循相似之迹:解锁协同过滤的核心推荐逻辑
  • Windows学习笔记(5)
  • 【大模型】大模型知识蒸馏 综述解读(Knowledge Distillation of Large Language Models)
  • Tesseract OCR技术初探(Python调用)
  • Python自动化模块:开启高效编程新时代
  • 小智AI音频开发 libopus + Eclipse C/C++ MinGW 编解码测试用例
  • 软件工程之需求工程(需求获取、分析、验证)
  • 动态规划算法题 小松鼠吃巧克力
  • Postman CORS 测试完全指南:轻松模拟跨域请求,排查 CORS 相关问题
  • Cursor 汉化教程
  • CAN 介绍
  • 在ArcGIS中导入气候tif文件出现 “输入与输出之间的基准面冲突” 警告
  • Python小练习系列 Vol.3:生成有效括号组合(回溯 + DFS)
  • 使用FastExcel时的单个和批量插入的问题
  • 【JavaScript】九、JS基础练习
  • 小红书xhs逆向算法还原(202503月更新)
  • [图论]万字解析图的最短路算法(详细带图解和代码)