• go语言入门(9)文本文件处理


    1,字符串处理

      字符串在开发中经常用到,包括用户的输入,数据库读取的数据等,我们经常需要对字符串进行分割、连接、转换等操作,我们可以通过Go标准库中的stringsstrconv两个包中的函数进行相应的操作。

    1.1字符串操作

    下面这些函数来自于strings包,这里介绍一些我平常经常用到的函数,更详细的请参考官方的文档。

    1) Contains

    func Contains(s, substr string) bool
    功能:字符串s中是否包含substr,返回bool值

    示例代码:

       fmt.Println(strings.Contains("seafood", "foo"))
        fmt.Println(strings.Contains("seafood", "bar"))
        fmt.Println(strings.Contains("seafood", ""))
        fmt.Println(strings.Contains("", ""))
        //运行结果:
        //true
        //false
        //true
        //true

    2)Join

    func Join(a []string, sep string) string
    功能:字符串链接,把slice a通过sep链接起来

    示例代码:

        s := []string{"foo", "bar", "baz"}
        fmt.Println(strings.Join(s, ", "))
        //运行结果:foo, bar, baz

    3)Index

    func Index(s, sep string) int
    功能:在字符串s中查找sep所在的位置,返回位置值,找不到返回-1

    示例代码:

        fmt.Println(strings.Index("chicken", "ken"))
        fmt.Println(strings.Index("chicken", "dmr"))
        //运行结果:
        //    4
        //    -1

    4)Repeat

    func Repeat(s string, count int) string
    功能:重复s字符串count次,最后返回重复的字符串

    示例代码:

        fmt.Println("ba" + strings.Repeat("na", 2))
        //运行结果:banana

    5)Replace

    func Replace(s, old, new string, n int) string
    功能:在s字符串中,把old字符串替换为new字符串,n表示替换的次数,小于0表示全部替换

    示例代码:

        fmt.Println(strings.Replace("oink oink oink", "k", "ky", 2))
        fmt.Println(strings.Replace("oink oink oink", "oink", "moo", -1))
        //运行结果:
        //oinky oinky oink
        //moo moo moo

    6)Split

    func Split(s, sep string) []string
    功能:把s字符串按照sep分割,返回slice
        fmt.Printf("%q
    ", strings.Split("a,b,c", ","))
        fmt.Printf("%q
    ", strings.Split("a man a plan a canal panama", "a "))
        fmt.Printf("%q
    ", strings.Split(" xyz ", ""))
        fmt.Printf("%q
    ", strings.Split("", "Bernardo O'Higgins"))
        //运行结果:
        //["a" "b" "c"]
        //["" "man " "plan " "canal panama"]
        //[" " "x" "y" "z" " "]
        //[""]

    7)Trim

    func Trim(s string, cutset string) string
    功能:在s字符串的头部和尾部去除cutset指定的字符串
     fmt.Printf("[%q]", strings.Trim(" !!! Achtung !!! ", "! "))
     //运行结果:["Achtung"]

    8)Fields

    func Fields(s string) []string
    功能:去除s字符串的空格符,并且按照空格分割返回slice
    fmt.Printf("Fields are: %q", strings.Fields("  foo bar  baz   "))
    //运行结果:Fields are: ["foo" "bar" "baz"]

    1.2,字符串转换

    字符串转化的函数在strconv中,如下也只是列出一些常用的。

    1)Append

    Append 系列函数将整数等转换为字符串后,添加到现有的字节数组中

        str := make([]byte, 0, 100)
        str = strconv.AppendInt(str, 4567, 10) //以10进制方式追加
        str = strconv.AppendBool(str, false)
        str = strconv.AppendQuote(str, "abcdefg")
        str = strconv.AppendQuoteRune(str, '')
    
        fmt.Println(string(str)) //4567false"abcdefg"'单'

    2)Format

    Format 系列函数把其他类型的转换为字符串。

        a := strconv.FormatBool(false)
        b := strconv.FormatInt(1234, 10)
        c := strconv.FormatUint(12345, 10)
        d := strconv.Itoa(1023)
    
        fmt.Println(a, b, c, d) //false 1234 12345 1023

    3)Parse

    Parse 系列函数把字符串转换为其他类型。

    package main
    
    import (
        "fmt"
        "strconv"
    )
    
    func checkError(e error) {
        if e != nil {
            fmt.Println(e)
        }
    }
    func main() {
        a, err := strconv.ParseBool("false")
        checkError(err)
        b, err := strconv.ParseFloat("123.23", 64)
        checkError(err)
        c, err := strconv.ParseInt("1234", 10, 64)
        checkError(err)
        d, err := strconv.ParseUint("12345", 10, 64)
        checkError(err)
        e, err := strconv.Atoi("1023")
        checkError(err)
        fmt.Println(a, b, c, d, e) //false 123.23 1234 12345 1023
    }

    2,正则表达式

    正则表达式是一种进行模式匹配和文本操纵的复杂而又强大的工具。

    详细的语法描述参考:http://code.google.com/p/re2/wiki/Syntax

    如果strings包能解决你的问题,那么就尽量使用它来解决。因为他们足够简单、而且性能和可读性都会比正则好。

    package main
    
    import (
        "fmt"
        "regexp"
    )
    
    func main() {
        context1 := "3.14 123123 .68 haha 1.0 abc 6.66 123."
    
        //MustCompile解析并返回一个正则表达式。如果成功返回,该Regexp就可用于匹配文本。
        //解析失败时会产生panic
        // d 匹配数字[0-9],d+ 重复>=1次匹配d,越多越好(优先重复匹配d)
        exp1 := regexp.MustCompile(`d+.d+`)
    
        //返回保管正则表达式所有不重叠的匹配结果的[]string切片。如果没有匹配到,会返回nil。
        //result1 := exp1.FindAllString(context1, -1) //[3.14 1.0 6.66]
        result1 := exp1.FindAllStringSubmatch(context1, -1) //[[3.14] [1.0] [6.66]]
    
        fmt.Printf("%v
    ", result1)
        fmt.Printf("
    ------------------------------------
    
    ")
    
        context2 := `
            <title>标题</title>
            <div>你过来啊</div>
            <div>hello mike</div>
            <div>你大爷</div>
            <body>呵呵</body>
        `
        //(.*?)被括起来的表达式作为分组
        //匹配<div>xxx</div>模式的所有子串
        exp2 := regexp.MustCompile(`<div>(.*?)</div>`)
        result2 := exp2.FindAllStringSubmatch(context2, -1)
    
        //[[<div>你过来啊</div> 你过来啊] [<div>hello mike</div> hello mike] [<div>你大爷</div> 你大爷]]
        fmt.Printf("%v
    ", result2)
        fmt.Printf("
    ------------------------------------
    
    ")
    
        context3 := `
            <title>标题</title>
            <div>你过来啊</div>
            <div>hello 
            mike
            go</div>
            <div>你大爷</div>
            <body>呵呵</body>
        `
        exp3 := regexp.MustCompile(`<div>(.*?)</div>`)
        result3 := exp3.FindAllStringSubmatch(context3, -1)
    
        //[[<div>你过来啊</div> 你过来啊] [<div>你大爷</div> 你大爷]]
        fmt.Printf("%v
    ", result3)
        fmt.Printf("
    ------------------------------------
    
    ")
    
        context4 := `
            <title>标题</title>
            <div>你过来啊</div>
            <div>hello 
            mike
            go</div>
            <div>你大爷</div>
            <body>呵呵</body>
        `
        exp4 := regexp.MustCompile(`<div>(?s:(.*?))</div>`)
        result4 := exp4.FindAllStringSubmatch(context4, -1)
    
        /*
            [[<div>你过来啊</div> 你过来啊] [<div>hello
                mike
                go</div> hello
                mike
                go] [<div>你大爷</div> 你大爷]]
        */
        fmt.Printf("%v
    ", result4)
        fmt.Printf("
    ------------------------------------
    
    ")
    
        for _, text := range result4 {
            fmt.Println(text[0]) //带有div
            fmt.Println(text[1]) //不带带有div
            fmt.Println("================
    ")
        }
    }
    View Code

    3,JSON处理

    4,文件操作

    4.1相关api

    1)建立与打开文件

    新建文件可以通过如下两个方法:

    func Create(name string) (file *File, err Error)
    根据提供的文件名创建新的文件,返回一个文件对象,默认权限是0666的文件,返回的文件对象是可读写的。
    
    func NewFile(fd uintptr, name string) *File
    根据文件描述符创建相应的文件,返回一个文件对象

    通过如下两个方法来打开文件:

    func Open(name string) (file *File, err Error)
    该方法打开一个名称为name的文件,但是是只读方式,内部实现其实调用了OpenFile。
    
    func OpenFile(name string, flag int, perm uint32) (file *File, err Error)
    打开名称为name的文件,flag是打开的方式,只读、读写等,perm是权限

    2)写文件

    func (file *File) Write(b []byte) (n int, err Error)
    写入byte类型的信息到文件
    
    func (file *File) WriteAt(b []byte, off int64) (n int, err Error)
    在指定位置开始写入byte类型的信息
    
    func (file *File) WriteString(s string) (ret int, err Error)
    写入string信息到文件

    3)读文件

    func (file *File) Read(b []byte) (n int, err Error)
    读取数据到b中
    
    func (file *File) ReadAt(b []byte, off int64) (n int, err Error)
    从off开始读取数据到b中

    4)删除文件

    func Remove(name string) Error
    调用该函数就可以删除文件名为name的文件

    4.2,示例

    1)写文件

    package main
    
    import (
        "fmt"
        "os"
    )
    
    func main() {
        fout, err := os.Create("./xxx.txt") //新建文件
        //fout, err := os.OpenFile("./xxx.txt", os.O_CREATE, 0666)
        if err != nil {
            fmt.Println(err)
            return
        }
    
        defer fout.Close() //main函数结束前, 关闭文件
    
        for i := 0; i < 5; i++ {
            outstr := fmt.Sprintf("%s:%d
    ", "Hello go", i)
            fout.WriteString(outstr)     //写入string信息到文件
            fout.Write([]byte("abcd
    ")) //写入byte类型的信息到文件
        }
    }
    View Code

    2)读文件

    func main() {
        fin, err := os.Open("./xxx.txt") //打开文件
        if err != nil {
            fmt.Println(err)
        }
        defer fin.Close()
    
        buf := make([]byte, 1024) //开辟1024个字节的slice作为缓冲
        for {
            n, _ := fin.Read(buf) //读文件
            if n == 0 {           //0表示已经到文件结束
                break
            }
    
            fmt.Println(string(buf)) //输出读取的内容
        }
    }
    View Code

    3)拷贝文件

    package main
    
    import (
        "fmt"
        "io"
        "os"
    )
    
    func main() {
        args := os.Args //获取用户输入的所有参数
    
        //如果用户没有输入,或参数个数不够,则调用该函数提示用户
        if args == nil || len(args) != 3 {
            fmt.Println("useage : xxx srcFile dstFile")
            return
        }
    
        srcPath := args[1] //获取输入的第一个参数
        dstPath := args[2] //获取输入的第二个参数
        fmt.Printf("srcPath = %s, dstPath = %s
    ", srcPath, dstPath)
    
        if srcPath == dstPath {
            fmt.Println("源文件和目的文件名字不能相同")
            return
        }
    
        srcFile, err1 := os.Open(srcPath) //打开源文件
        if err1 != nil {
            fmt.Println(err1)
            return
        }
    
        dstFile, err2 := os.Create(dstPath) //创建目的文件
        if err2 != nil {
            fmt.Println(err2)
            return
        }
    
        buf := make([]byte, 1024) //切片缓冲区
        for {
            //从源文件读取内容,n为读取文件内容的长度
            n, err := srcFile.Read(buf)
            if err != nil && err != io.EOF {
                fmt.Println(err)
                break
            }
    
            if n == 0 {
                fmt.Println("文件处理完毕")
                break
            }
    
            //切片截取
            tmp := buf[:n]
            //把读取的内容写入到目的文件
            dstFile.Write(tmp)
        }
    
        //关闭文件
        srcFile.Close()
        dstFile.Close()
    }
    View Code
  • 相关阅读:
    C风格字符串大写转小写
    指针的引用在函数中的应用
    Debug和Release区别
    差分约束系统(System Of Difference Constraints)
    poj_2299UltraQuickSort && poj_1804Brainman
    计算几何基础——矢量和叉积
    推荐ALGORITHM专题
    后缀数组之倍增法
    静态邻接表的简单实现
    归并排序&&树状数组求逆序数
  • 原文地址:https://www.cnblogs.com/xdyixia/p/11896134.html
Copyright © 2020-2023  润新知