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\n", strings.Split("a,b,c", ","))
    fmt.Printf("%q\n", strings.Split("a man a plan a canal panama", "a "))
    fmt.Printf("%q\n", strings.Split(" xyz ", ""))
    fmt.Printf("%q\n", 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\n", result1)
    fmt.Printf("\n------------------------------------\n\n")

    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\n", result2)
    fmt.Printf("\n------------------------------------\n\n")

    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\n", result3)
    fmt.Printf("\n------------------------------------\n\n")

    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\n", result4)
    fmt.Printf("\n------------------------------------\n\n")

    for _, text := range result4 {
        fmt.Println(text[0]) //带有div
        fmt.Println(text[1]) //不带带有div
        fmt.Println("================\n")
    }
}
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\n", "Hello go", i)
        fout.WriteString(outstr)     //写入string信息到文件
        fout.Write([]byte("abcd\n")) //写入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\n", 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

 

posted @ 2019-11-20 11:04  xdyixia  阅读(847)  评论(0编辑  收藏  举报