文件操作、Json数据协议、 错误处理

1、终端读写

  操作终端相关
   文件句柄常量
   os.Stdin:标准输入
   os.Stdout:标准输出
   os.Stderr:标准错误输出

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.Println("From the string we read: ", f, i, s)  //可以打印出变量
    fmt.Printf("Hi %s %s!\n", firstName, lastName)     //只可以打印出格式化的字符串,字符串类型的变量,不可以输出整型变量和整型
    fmt.Scan(&firstName, &lastName)            //输入的参数按空格分开
    fmt.Scanln(&firstName, &lastName)        //Scanln和Scan非常类似,只是Scanln只会接受一个回车,收到回车就扫描结束了
    fmt.Scanf("%s , %s", &firstName, &lastName) 
    /*
    1、Scanf中间有一个逗号,但逗号和%s间有空格,因为Scanf是用空格来区分不同的参数的。
    2、输入的参数firstName , lastName格式与Scanf中指定的fmt要一致。
    3、中间的逗号,Scanf会自动格式匹配不会添加到变量中
    */
    fmt.Sscanf(input, format, &f, &i, &s) 
}
fmt

 bufio带缓冲区的读写

package main

import (
    "bufio"
    "fmt"    
    "os"    
)

func main() {

    reader := bufio.NewReader(os.Stdin) //从终端接收输入的信息
    line, err := reader.ReadString('\n') //双引号是字符串,单引号是字符,读取一行结束
    if err != nil {
        fmt.Println("read error:", err)
        return
    }    
}

 

package main

import (
    "bufio"
    "fmt"
    "math/rand"    
    "time"
)

type RandStr struct {
}

func (r *RandStr) Read(p []byte) (n int, err error) {
    fmt.Printf("Len(p)=%d\n", len(p))

    source := "abcdefghijk0123456789"
    for i := 0; i < 32; i++ {
        index := rand.Intn(len(source))  
        p[i] = source[index]  //P的长度已经分配好了,不能使用append方法,会越界
    }
    p[32] = '\n'
    return len(p), nil
}

func main() {    
    rand.Seed(time.Now().UnixNano())  //修改随机数种子
    var randStr = &RandStr{}
    randReader := bufio.NewReader(randStr)  //自己实现Read接口
    lineByte, prefix, _ := randReader.ReadLine()   
    fmt.Printf("rand:%s prefix:%v\n", string(lineByte), prefix)
}
自己实现read接口

练习:从终端读取一行字符串,统计英文、数字、空格以及其他字符的数量。

package main

import (
    "os"
    "bufio"
    "fmt"
)
func stat(str string) {
    var en_count int
    var sp_count int
    var num_count int
    var other_count int
    utf8Arr := []rune(str)
    for _, v := range utf8Arr {
        if v >= 'a' && v <= 'z' || v >= 'A' && v <= 'Z' {
            en_count++
            continue
        }
        if v == ' ' {
            sp_count++
            continue
        }
        if v >= '0' && v<= '9' {
            num_count++
            continue
        }
        other_count++
    } 
    fmt.Printf("en=%d sp=%d num=%d other=%d\n", en_count, sp_count, num_count, other_count)
}


func main(){
    reader := bufio.NewReader(os.Stdin)
    line, err := reader.ReadString('\n')
    if err != nil {
        fmt.Printf("read string failed, err:%v\n", err)
        return
    }

    stat(line)
}
View Code

 文本文件读写

1、os.File封装所有文件相关操作,之前讲的 os.Stdin,os.Stdout, os.Stderr都是 *os.File

( 程序启动自动打开句柄os.Stdin,os.Stdout, os.Stderr,内部都实现了Read方法,os.File内部也实现了Read方法)

  a、打开一个文件进行读操作: os.Open(name string) (*File, error)

  b、关闭 一个 文件:File.Close()

package main 

import (
    "os"
    "fmt"
    "io"    
    
)

func testFile() {
    // 文件没有一行一行读取的功能
    file, err := os.Open("D:/运维人员如何最大限度避免误删除文件-演示文件.txt")
    if err != nil {
        fmt.Println("open file failed:", err)
        return
    }

    defer file.Close()     //关闭文件句柄
    var data [1024]byte    //传一个数据进file文件句柄
    for {                   //循环读取
        n, err := file.Read(data[:])  //n为读取的有效字节
        if err == io.EOF {  //读到文件末尾
            break
        } 
        if err != nil {     //错误信息
            fmt.Printf("read file error:%s\n", err)
            return
        }

        str := string(data[0:n])
        fmt.Println(str)
    }
}


func main(){

    testFile()
}
大文件读取
package main 

import (
    "os"
    "fmt"
    "io"
    "bufio"
)
func testBufIO() {
    //文件如果要一行一行读取,可以用bufio读取
    file, err := os.Open("D:/运维人员如何最大限度避免误删除文件-演示文件.txt")
    if err != nil {
        fmt.Println("open file failed:", err)
        return
    }

    defer file.Close()

    reader := bufio.NewReader(file)
    for {
        line, err := reader.ReadString('\n')  //一行一行读取
        if err == io.EOF {
            break
        }
        if err != nil {
            fmt.Printf("read file error:%s\n", err)
            return
        }
        fmt.Println(line)
    }
}

func main(){    
    testBufIO()    
}
带缓冲的大文件读取
package main 

import (
    "os"
    "fmt"    
    "io/ioutil"
)
func testIoUtil() {
    //一次读取一个文件
    data, err := ioutil.ReadFile("D:/运维人员如何最大限度避免误删除文件-演示文件.txt") 
    //ReadFile方法内部自己打开文件
    //Readall传一个实现了Read方法的接口进去
    if err != nil {
        fmt.Printf("read file failed:%v\n", err)
        return
    }
    fmt.Printf("%s\n", string(data))
}

func main(){    
    testIoUtil()
}
一次性读取小文件

 读取压缩文件

package main

import (
    "io"
    "bufio"
    "compress/gzip"  //导入相应的压缩格式
    "fmt"
    "os"
)

func main(){
    file, err := os.Open("D:/张导讲命令.txt.gz")
    if err != nil {
        fmt.Println("open file failed:", err)
        return
    }
    defer file.Close()

    reader, err := gzip.NewReader(file)  //解压文件句柄reader只能整体读取,不能按行读取
    if err != nil {
        fmt.Printf("gzip failed, err:%v\n", err)
        return
    }
    bufReader := bufio.NewReader(reader)   //bufio可以按行读取
    for {
        line, err := bufReader.ReadString('\n')
        if err != nil {
            if err == io.EOF {
                break
            }
            fmt.Printf("read failed, err:%v\n", err)
            return
        }
        fmt.Printf("%s", line)
    }
}
View Code

文件写入

os.OpenFile(“output.dat”, os.O_WRONLY|os.O_CREATE, 0666)

第二个参数: 打开文件模式:   第三个参数:权限控制: 

1. os.O_WRONLY:只写      r ——> 0004 

2. os.O_CREATE:创建文件    w——> 0002 

3. os.O_RDONLY:只读      x——> 0001   

4. os.O_RDWR:读写  

5. os.O_TRUNC :清空  

package main


import (
    "os"
    "fmt"
)

func testWriteFile() {

    file , err := os.OpenFile("D:/mylog.txt", os.O_WRONLY|os.O_CREATE, 0666)
    if err != nil {

        fmt.Printf("open file failed:%v\n", err)
        return
    }
    defer file.Close()

    for i := 0; i < 10; i++{
        file.WriteString(fmt.Sprintf("hello %d\n", i))
    }

}

func main() {
    testWriteFile()
}
View Code
package main

import (
    "bufio"
    "fmt"
    "os"
)

func main() {
    outputFile, outputError := os.OpenFile("output.dat", os.O_WRONLY|os.O_CREATE, 0666)

    if outputError != nil {
        fmt.Printf("An error occurred with file creation\n")
        return
    }
    defer outputFile.Close()
    outputWriter := bufio.NewWriter(outputFile) //bufio写入,速度较快
    outputString := "hello world!\n"
    for i := 0; i < 10; i++ {
        outputWriter.WriteString(outputString)
    }
    outputWriter.Flush()
}
bufio写入

 文件

package main

import (
    "fmt"
    "io"
    "os"
)

func main() {
    CopyFile("target.txt", "source.txt")
    fmt.Println("Copy done!")
}

func CopyFile(dstName, srcName string) (written int64, err error) { 
    src, err := os.Open(srcName)
    if err != nil {
        return
    }
    defer src.Close()
    dst, err := os.OpenFile(dstName, os.O_WRONLY|os.O_CREATE, 0644)
    if err != nil {
        return
    }
    defer dst.Close()
    return io.Copy(dst, src)   //文件拷贝
}
View Code

命令行参数

os.Args是 一个string的切片, 用来存储所有的命令行参数

package main

import (
    "os"
    "fmt"    
)

func main(){
    for index, val := range os.Args{ //第一参数永远是可执行文件
        fmt.Printf("args[%d] = %s\n",index,val)
    }
}

flag包的使用,用来解析命令行参数:
flag.BoolVar(&test, "b", false, "print on newline")
flag.StringVar(&str, "s", "", "print on newline")
flag.IntVar(&count, "c", 1001, "print on newline")

package main

import (
    //"os"
    "fmt"
    "flag"
)

var (
    conf string
    level int
)

func init(){
    flag.StringVar(&conf, "c", "D:/etc/test.conf", "请指定配置文件路径") //第三个参数是默认值,第四个参数是参数说明
    flag.IntVar(&level, "l", 8, "请指定日志级别")
    flag.Parse()  //要解析才生效
}

func main(){    
    fmt.Printf("conf is:%s\n", conf)
    fmt.Printf("level is:%d\n", level)
}

//在命令行输入cmd_test.exe -c "etc/test.conf" l 10
命令行参数解析
package main
import (
    "bufio"
    "flag"
    "fmt"
    "io"
    "os"
)

func cat(r *bufio.Reader) {
    for {
        buf, err := r.ReadBytes('\n')
        if err == io.EOF {
            break
        }
        fmt.Fprintf(os.Stdout, "%s", buf) //文件读取输出到终端
    }
}
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))        
    }
    
}
带缓冲区的文件读取输出到终端
package main


import (
    "os"
    "fmt"    
    "io"
)

func cat (filename string) {
    file, err := os.Open(filename) 
    if err != nil {
        fmt.Printf("open %s failed, err:%v\n", filename, err)
        return
    }
    defer file.Close()
    io.Copy(os.Stdout, file)  //将文件的内容输出到终端,以io.Copy方式实现
}

func main() {
    if (len(os.Args) == 1) {
        fmt.Println("请指定文件名")
        return
    }

    for i := 1; i <len(os.Args);i++{
        cat(os.Args[i])
    }
}
以copy方式实现文件输出到终端
package main

import (
    "bufio"
    "fmt"
    "os"
)


func main() {
    fmt.Fprintf(os.Stdout, "%s\n", "hello world! - unbuffered")
    buf := bufio.NewWriter(os.Stdout)
    fmt.Fprintf(buf, "%s\n", "hello world! - buffered")
    buf.Flush()
}
带缓冲区的终端取输出到终端

 

Json数据协议

1.导 入包:Import “encoding/json”
2.序列列化: json.Marshal(data interface{})
3.反序列列化: json.UnMarshal(data []byte, v interface{})

package main


import (
    "encoding/json"
    "fmt"
    "math/rand"
    "os"    
)

type Student struct {
    Name string `json:"name"`    //定义json串里面的key
    Age int `json:"age"` 
    Score float32 `json:"score"`
}

func testWriteFile(){
    var stus []*Student
    for i := 0; i <1000; i++{
        stu := &Student {
            Name:fmt.Sprintf("stu%d", i),
            Age:rand.Intn(100),
            Score:rand.Float32()*100,
        }
        stus = append(stus, stu)
    }

    data, err := json.Marshal(stus)  //序列化,可以传任何数据类型进去,因为是空接口
    if err != nil {
        fmt.Printf("json failed, err:%v\n", err)
        return
    }

    file, err := os.OpenFile("d:/stu.dat", os.O_CREATE|os.O_WRONLY, 0666)  //打开文件
    if err != nil {
        fmt.Printf("file failed, err:%v\n", err)
        return
    }
    defer file.Close()

    n, err := file.Write(data)  //将json字符串写入文件
    if err != nil {
        fmt.Printf("write failed, err:%v\n", err)
        return
    }
    fmt.Printf("write %d succ\n", n)
}

func main(){
    testWriteFile()    
}
序列化
package main


import (
    "encoding/json"
    "fmt"    
    "os"
    "io/ioutil"
)

type Student struct {
    Name string `json:"name"`    //定义json串里面的key
    Age int `json:"age"` 
    Score float32 `json:"score"`
}

func testReadFile(){
    file, err := os.OpenFile("d:/stu.dat", os.O_RDONLY, 0666)
    if err != nil {
        fmt.Printf("file failed, err:%v\n", err)
        return
    }
    defer file.Close()

    data, err := ioutil.ReadAll(file)
    if err != nil {
        fmt.Printf("read all failed, err:%v\n", err)
    }

    var stus []*Student
    err = json.Unmarshal(data, &stus)  //反序列化
    if err != nil {
        fmt.Printf("json unmarshal failed, err:%v\n", err)
        return
    }
    fmt.Printf("total student:%d\n", len(stus))
    for i := 0; i <10; i++{
        fmt.Printf("student:%#v\n", stus[i])
    }
}

func main(){    
    testReadFile()
}
反序列化

 

错误处理

定义错误

package main

import (
    "errors"
    "fmt"
)

var errNotFound error = errors.New("Not found error")

func main() {
    fmt.Printf("error: %v", errNotFound)
}

Panic&Recover

package main

import (
    "fmt"
    "time"
)

func set(p *int) {
    *p = 123 //空指针赋值挂掉
}

func test() {

    defer func() {
        err := recover()
        if err != nil {
            fmt.Printf("panic:%v\n", err) //捕获异常,不让程序挂掉
        }
    }()
    var p *int
    set(p)
    fmt.Printf("*p=%d\n", *p)
}

func main() {
    for {
        test()
        time.Sleep(time.Second)
    }
}
View Code

 

posted @ 2018-01-21 22:56  shy车队破风手  阅读(218)  评论(0编辑  收藏  举报