• 八、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这个结构体中
    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('
    ')
       if err!=nil{
          fmt.Println("read string failed ,err:",err)
          return
       }
       fmt.Printf("read str succ ret:%s
    ",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('
    ')
       if err != nil {
          fmt.Println("read string failed",err)
          return
       }
       fmt.Printf("read str succ,ret:%s
    ",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:	est")
       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('
    ')
          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 == '	':
                Count.SpaceCount++
             case v >='0' && v <= '9':
                Count.NumCount++
             default:
                Count.OtherCount++
             }
          }
       }
       fmt.Println("char Count :%d
    ",Count.ChCount)
       fmt.Println("Num Count :%d
    ",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:	est.txt"
       outputFile:="C:	est"
       //把文件全部读取到文件里面
       buf,err:=ioutil.ReadFile(inpuitFile)
       if err!=nil{
          fmt.Fprintf(os.Stderr,"File Error%s
    ",err)
          return
       }
    
       //写
       fmt.Printf("%s 
    ",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
    ",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
    ",err)
          return
       }
       r=bufio.NewReader(fz)          //创建一个为fz大小的缓冲区
       for{
          line,err:=r.ReadString('
    )   //在缓冲区内读取文件
          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 
    "
       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('
    ')
          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
    ",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
    ",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
    ",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()的结果

  • 相关阅读:
    Frans Kaashoek获得ACM青年研究者奖 狼人:
    7款相当给力的上网本应用 狼人:
    Google对外发布C++编码规范 狼人:
    10个超棒的HTML5素描及绘画设计工具 狼人:
    Fix Bug的五个阶段 狼人:
    【观点】如果你不是程序员 该如何雇佣程序员呢 狼人:
    8款超赞的最新jQuery插件工具 狼人:
    对Web设计有用的10组免费漂亮的图标 狼人:
    C语言,美丽的语言 狼人:
    环境系统工具[CentOS]安装rar解压工具
  • 原文地址:https://www.cnblogs.com/pyrene/p/8094321.html
Copyright © 2020-2023  润新知