分享
  1. 首页
  2. 文章

八、golang文本操作、json协议

pyrene · · 2202 次点击 · · 开始浏览
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

一、终端读写

操作终端相关文件语句常量,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这个结构体中
View Code

带缓冲区的读写 从终端去读取数据

首先写道缓冲区里面,然后go或者系统再刷到文件里面,用于提高性能

下面是带缓冲区的读的代码

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:如果需要读写 操作用这个

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这个错误

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这个包是一行一行把文件读取到缓冲区里面

读取整个文件实例

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)关闭文件
View Code

文件写入:

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)把缓冲区中的数据刷入到磁盘中
View Code

拷贝文件

源码简单,根据接口来实现

看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可以实现文件拷贝到另一个文件,也可以实现文件拷贝到终端,也可以实现文件拷贝到网络中
View Code

带缓冲区的读写

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序列化结构体

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()的结果


有疑问加站长微信联系(非本文作者)

本文来自:博客园

感谢作者:pyrene

查看原文:八、golang文本操作、json协议

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

关注微信
2202 次点击
暂无回复
添加一条新回复 (您需要 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传

用户登录

没有账号?注册
(追記) (追記ここまで)

今日阅读排行

    加载中
(追記) (追記ここまで)

一周阅读排行

    加载中

关注我

  • 扫码关注领全套学习资料 关注微信公众号
  • 加入 QQ 群:
    • 192706294(已满)
    • 731990104(已满)
    • 798786647(已满)
    • 729884609(已满)
    • 977810755(已满)
    • 815126783(已满)
    • 812540095(已满)
    • 1006366459(已满)
    • 692541889

  • 关注微信公众号
  • 加入微信群:liuxiaoyan-s,备注入群
  • 也欢迎加入知识星球 Go粉丝们(免费)

给该专栏投稿 写篇新文章

每篇文章有总共有 5 次投稿机会

收入到我管理的专栏 新建专栏