【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可为的常量:

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

关闭文件用到的方法:

使用案例:

Go 复制代码
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)带缓冲读文件

Go 复制代码
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)一次性读文件

案例:

Go 复制代码
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)创建新文件并写入数据

Go 复制代码
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)打开原有文件,将原内容覆盖写入

Go 复制代码
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)打开原有文件,在原文件上追加写入

Go 复制代码
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)打开原有文件,并进行读和写操作

Go 复制代码
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,说明文件或文件夹不存在
  • 如果返回的错误为其它类型,则不确定是否在存在
Go 复制代码
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拷贝文件

Go 复制代码
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.命令行参数基本使用

Go 复制代码
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包,可以方便的解析命令行参数,并且参数顺序可以随意

Go 复制代码
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包处理命令行参数

Go 复制代码
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)对象:用 {} 表示,包含键值对

Go 复制代码
{
  "name": "Alice",
  "age": 25
}

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

Go 复制代码
["apple", "banana", "orange"]

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

JSON在线解析: JSON在线解析

3.3JSON序列化

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

案例:

Go 复制代码
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)的过程

Go 复制代码
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字符串是通过程序获取到的,则不需要再对"进行转义处理

结语

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

相关推荐
TDengine (老段)2 分钟前
基于 TSBS 标准数据集下 TimescaleDB、InfluxDB 与 TDengine 性能对比测试报告
java·大数据·开发语言·数据库·时序数据库·tdengine·iotdb
lgily-12255 分钟前
常用的设计模式详解
java·后端·python·设计模式
意倾城1 小时前
Spring Boot 配置文件敏感信息加密:Jasypt 实战
java·spring boot·后端
火皇4051 小时前
Spring Boot 使用 OSHI 实现系统运行状态监控接口
java·spring boot·后端
rylshe13141 小时前
在scala中sparkSQL连接mysql并添加新数据
开发语言·mysql·scala
小宋加油啊1 小时前
Mac QT水平布局和垂直布局
开发语言·qt·macos
薯条不要番茄酱1 小时前
【SpringBoot】从零开始全面解析Spring MVC (一)
java·spring boot·后端
MyhEhud1 小时前
kotlin @JvmStatic注解的作用和使用场景
开发语言·python·kotlin
想睡hhh2 小时前
c++进阶——哈希表的实现
开发语言·数据结构·c++·散列表·哈希
Clown952 小时前
Go语言爬虫系列教程(一) 爬虫基础入门
开发语言·爬虫·golang