八、golang文本操作、json协议
一、终端读写
操作终端相关文件语句常量,go所有的都是接口
os.Stdin:标准输入
os.Stdout:标准输入,只要实现输出这个接口,打印到终端,
os.Stderr:标准错误输出
os.OpenFile(“路径”,模式):打开文件
终端读写实例
package main
import(
“fmt”
)
var (
firstName,lastName,s string
I int
f float32
input =”56.12/5212/GO”
format =”%f /%d/%s”
)
func main(){
fmt.Println(“please enter your full name”) //打印一行的输出
fmt.Scanln(&firstName,&lastName) //只能输入字符串
//fmt.Scanf(input,format,&f,&I,&s) //格式化输入
fmt.Printf() //格式化输出
fmt.Sscanf(input,format,&f,&I,&s) //从一个字符串中格式化输入
fmt.Println(“from the we read ”,f,I,s)
}

package main import "fmt" type Student struct{ Name string Age int Score float32 } func main(){ var str ="stu01 18 89.92" var stu Student fmt.Sscanf(str,"%s %d %f",&stu.Name,&stu.Age,stu.Score) fmt.Println(stu) } {stu01 18 0} 上面就是把str字符串中的内容格式化输入到了stu这个结构体中
带缓冲区的读写 从终端去读取数据
首先写道缓冲区里面,然后go或者系统再刷到文件里面,用于提高性能
下面是带缓冲区的读的代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | package main import ( "bufio" "os" "fmt" ) //注意单引号是byte,双引号等是字符串 func main(){ //首先用到带缓冲区的包bufio,newReader返回一个新的Reader,具有默认大小 reader :=bufio.NewReader(os.Stdin) //参数是接口,这里接口是标准输入 //读包含数据的字符串,包括分隔符,由于上面返回Reader,所以要用Read。。方法读取,参数byte str,err:=reader.ReadString( '\n' ) if err!=nil{ fmt.Println( "read string failed ,err:" ,err) return } fmt.Printf( "read str succ ret:%s\n" ,str) } 执行结果 D:\project>go build go_dev/day7/example2 D:\project>example2.exe this is my book yo //手动输入 read str succ ret: this is my book yo |
小结:
1)用bufio.NewReader创建一个新的Reader,返回值默认大小的Reader,也就是创建缓冲区然后把文件读入缓冲区
2)然后根据上面的返回值进行Read。。。方法读取,返回错误和读出的数据
3)进行err判断
文件读写
open:返回一个文件用于读取数据
OpenFile:如果需要读写 操作用这个
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | package main import ( "os" "fmt" "bufio" ) func main(){ file,err:=os.Open( "C:/test.txt" ) if err != nil{ fmt.Println( "read file err" ,err) return } defer file.Close() reader:=bufio.NewReader(file) str,err:=reader.ReadString( '\n' ) if err != nil { fmt.Println( "read string failed" ,err) return } fmt.Printf( "read str succ,ret:%s\n" ,str) } 上面程序小结: 1)打开文件,读取内容,判断错误输出 2)defer关闭文件 3)创建缓冲区并且向缓冲区写入文件 4)读取缓冲区数据,并且判断错误输出 |
练习:从文件中读取一行字符串,统计英文、数字、空格以及其他字符的数量
读取到文件末尾会返回io.EOF这个错误
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 | package main import( "fmt" "os" "bufio" "io" ) type CharCount struct { ChCount int NumCount int SpaceCount int OtherCount int } func main(){ file,err:=os.Open( "C:\test" ) if err!=nil{ fmt.Println( "read file err" ,err) return } defer file.Close() var Count CharCount str:=bufio.NewReader(file) //创造缓冲区 //下面是一行一行的从缓冲区里面读取内容然后统计 for { str1,err:=str.ReadString( '\n' ) if err==io.EOF{ //读到文件尾部会返回EOF错误 break } if err!=nil { //如果真的出问题打印出来问题 fmt.Println( "read str1 fail" , err) return } runeArr :=[]rune(str1) //把字符转换成中文的字符数组 for _,v :=range runeArr { switch { case v>= 'a' && v<= 'z' : fallthrough case v>= 'A' && v<= 'Z' : Count.ChCount++ case v == ' ' || v == '\t' : Count.SpaceCount++ case v >= '0' && v <= '9' : Count.NumCount++ default : Count.OtherCount++ } } } fmt.Println( "char Count :%d\n" ,Count.ChCount) fmt.Println( "Num Count :%d\n" ,Count.NumCount) fmt.Println( "Space Count :%d" ,Count.SpaceCount) fmt.Println( "other Count :%d" ,Count.OtherCount) } |
1、os.File封装所有文件相关操作,之间的os.Stdin,os.Stdout,os.Stderr都是*os.File(结构体)
a)打开一个文件进行读操作 os.Open(name string)(*File,error) //第一个括号是全路径,返回file
b)关闭一个文件:File.Close()
如果不关闭的话,linux最大为65535个文件句柄,如果超过最大数的话,那么以后再打的时候就一直是失败的
io/ioutil这个文件包可以一下把文件全部读取出来,读取到缓冲区里面
bufio这个包是一行一行把文件读取到缓冲区里面
读取整个文件实例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | package main import ( "fmt" "io/ioutil" "os" ) func main(){ inpuitFile:= "C:\test.txt" outputFile:= "C:\test" //把文件全部读取到文件里面 buf,err:=ioutil.ReadFile(inpuitFile) if err!=nil{ fmt.Fprintf(os.Stderr, "File Error%s\n" ,err) return } //写 fmt.Printf( "%s \n" , string (buf)) err=ioutil.WriteFile(outputFile,buf,0x1) //第三个参数是十六进制数 if err!=nil{ panic(err.Error()) } } |
读取压缩文件
gzip.NewReader()参数接受一个文件句柄,读一部分文件数据解压缩,返回值是一个具有解压缩的功能
再把上面的具有解压缩的返回值放入到缓冲区里面,返回值为带缓冲区的解压缩功能

package main import ( "bufio" "os" "fmt" "compress/gzip" ) func main(){ fName:="myFile.gz" var r *bufio.Reader fi,err:=os.Open(fName) //打开文件 if err!=nil{ fmt.Fprintf(os.Stderr,"%v can`t open %s:error:%s\n",os.Args[0],fName,err) os.Exit(1) } defer fi.Close() //关闭文件 fz,err:=gzip.NewReader(fi) //创建fi大小的缓冲区进行解压 if err!=nil{ fmt.Fprintf(os.Stderr,"open gizp failed err%v\n",err) return } r=bufio.NewReader(fz) //创建一个为fz大小的缓冲区 for{ line,err:=r.ReadString('\n) //在缓冲区内读取文件 if err!=nil{ fmt.Println("Done reading file") os.Exit() } fmt.Println(line) } } 解压缩文件小结: 1)打开文件 2)创建需要解压缩文件大小的缓冲区进行解压文件 3)创造解压后文件大小的缓冲区 4)在缓冲区内读取文件 5)关闭文件
文件写入:
os.OpenFile(“output.dat”,os.O_WRONLY|os.O_CREATE,0666)
第一个参数是文件路径,第二个参数是模式
第二个参数
1.os.O_WRONLY:只写
2,os.O_CREATE: 创建文件
3.os.O_RDONLY:只读
4.os.O_RDWR,读写
5.os.O_TRUNC:清空
12 14
第三个参数:权限控制
r--à04
w--à02
x--à01
这里第三个三处分别是属主,数组,其他人

package main import ( "os" "fmt" "bufio" ) func main(){ outputFile,outputError:=os.OpenFile("output.da",os.O_WRONLY|os.O_CREATE,0666) //打开文件写 if outputError != nil{ fmt.Printf("An error occured with file crea ion!") return } defer outputFile.Close() outputWrite:=bufio.NewWriter(outputFile) //创建一个写入文件大小的缓冲区 outputString:="hello word \n" for i:=0;i<10;i++{ outputWrite.WriteString(outputString) //把数据写入到缓冲区 } outputWrite.Flush() //把缓冲区的数据刷入到磁盘中,防止数据丢失 } 写入文件小结: 1)打开文件设置权限以及方式 2)defer关闭文件 3)创建一个文件大小的缓冲区 4)把数据写入缓冲区 5)把缓冲区中的数据刷入到磁盘中
拷贝文件
源码简单,根据接口来实现
看copy源码

func Copy(dst Writer, src Reader) (written int64, err error) { return copyBuffer(dst, src, nil) } // CopyBuffer is identical to Copy except that it stages through the // provided buffer (if one is required) rather than allocating a // temporary one. If buf is nil, one is allocated; otherwise if it has // zero length, CopyBuffer panics. func CopyBuffer(dst Writer, src Reader, buf []byte) (written int64, err error) { if buf != nil && len(buf) == 0 { panic("empty buffer in io.CopyBuffer") } return copyBuffer(dst, src, buf) } // copyBuffer is the actual implementation of Copy and CopyBuffer. // if buf is nil, one is allocated. func copyBuffer(dst Writer, src Reader, buf []byte) (written int64, err error) { // If the reader has a WriteTo method, use it to do the copy. // Avoids an allocation and a copy. if wt, ok := src.(WriterTo); ok { return wt.WriteTo(dst) } // Similarly, if the writer has a ReadFrom method, use it to do the copy. if rt, ok := dst.(ReaderFrom); ok { return rt.ReadFrom(src) } if buf == nil { //32k为单位进行拷贝 buf = make([]byte, 32*1024) } for { nr, er := src.Read(buf) //首先读32k数据 if nr > 0 { //读数据成功 nw, ew := dst.Write(buf[0:nr]) //把把数据写入到目的文件之中 if nw > 0 { written += int64(nw) //写入 } if ew != nil { // err = ew break } if nr != nw { //如果读的和写的数据数量不相等 err = ErrShortWrite //返回错误 break } } if er != nil { //文件读完的话 if er != EOF { //如果文件没有读到末尾 err = er //错误赋值 } break } } return written, err } copy可以实现文件拷贝到另一个文件,也可以实现文件拷贝到终端,也可以实现文件拷贝到网络中
带缓冲区的读写
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | package main import ( "bufio" "io" "fmt" "os" "flag" ) func cat(r *bufio.Reader){ //参数接收一个缓冲区 for { buf,err := r.ReadByte( '\n' ) if err == io.EOF{ //如果文件读到末尾那么就结束 break } fmt.Fprintf(os.Stdout, "%s" ,buf) return } } func main(){ flag.Parse() //预处理 if flag.NArg() == 0 { //如果参数为空,那么就写入 cat(bufio.NewReader(os.Stdin)) //函数接手一个缓冲区大小的参数 } for i:=0;i<flag.NArg();i++{ f,err := os.Open(flag.Arg(i)) if err != nil{ fmt.Fprintf(os.Stderr, "%s:error reading from %s:%s\n" ,os.Args[0],flag.Arg(i),err.Error()) } continue cat(bufio.NewReader(f)) } } |
JSON数据协议
go如果和其他语言有交互,那么就需要序列化为json字符串,然后通过网络传输传递给程序,然后反序列化为其他语言
1)导入包:Import “encoding/json”
2)序列化:json.Marshal(data interface{})
3)反序列化:json.UnMarshal(data []byte,v interface{})
Json序列化结构体
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 | package main import ( "encoding/json" "fmt" ) type User struct { Username string `json: "username" ` NickName string Age int Birthday string Sex string Email string Phone string } //struct的json形式 func testStruct(){ user1 :=&User{ Username: "user1" , NickName: "pyrene" , Age:18, Birthday: "2008/8/8" , Sex: "男" , Email: "mahuateng@qq.com" , Phone: "18" , } data,err := json.Marshal(user1) //返回值是字符数组 if err != nil{ fmt.Println( "json.Marshal faild,err" ,err) return } //由于返回值是字符数组,所以要转化为string fmt.Printf( "%s\n" , string (data)) } //整形的json func testInt(){ var age = 100 data,err := json.Marshal(age) if err != nil{ fmt.Println( "int json.Marshl failed ,err" ,err) return } fmt.Printf( "%s\n" ,data) } func testMap(){ var m map[ string ] interface {} m=make(map[ string ] interface {}) m[ "username" ]= "user1" m[ "age" ]=18 m[ "sex" ]= "man" data,err := json.Marshal(m) if err != nil { fmt.Println( "map json.Marshal failed,err" ,err) return } fmt.Println( string (data)) } //slice的json方式 这里定义了一个slice然后里面的元素是map类型 func testSlice(){ var m map[ string ] interface {} var s []map[ string ] interface {} m=make(map[ string ] interface {}) m[ "username" ]= "user1" m[ "age" ]=18 m[ "sex" ]= "man" s=append(s,m) m[ "username" ]= "user2" m[ "age" ]=18 m[ "sex" ]= "female" s=append(s,m) data,err := json.Marshal(s) if err != nil { fmt.Println( "map json.Marshal failed,err" ,err) return } fmt.Println( string (data)) } func main(){ testStruct() testInt() //100 testMap() testSlice() } 把打印的结果放到json.cn网站上面,生成如下: testStruct()的json结果: |
testMap()的结果
testSlice()的结果
testSlice()的结果
【推荐】还在用 ECharts 开发大屏?试试这款永久免费的开源 BI 工具!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· .NET制作智能桌面机器人:结合BotSharp智能体框架开发语音交互
· 软件产品开发中常见的10个问题及处理方法
· .NET 原生驾驭 AI 新基建实战系列:向量数据库的应用与畅想
· 从问题排查到源码分析:ActiveMQ消费端频繁日志刷屏的秘密
· 一次Java后端服务间歇性响应慢的问题排查记录
· 互联网不景气了那就玩玩嵌入式吧,用纯.NET开发并制作一个智能桌面机器人(四):结合BotSharp
· 一个基于 .NET 开源免费的异地组网和内网穿透工具
· 《HelloGitHub》第 108 期
· Windows桌面应用自动更新解决方案SharpUpdater5发布
· 我的家庭实验室服务器集群硬件清单