• 【Hello Go】Go语言文本文件处理


    字符串处理

    字符串在开发的过程中经常用到 比如在用户的输入或者是数据库的读取操作中

    我们经常需要对于字符串进行分割 链接 旋转等操作 我们可以通过Go语言标准库中的strings 和 strconv 两个包中的函数进行相应的操作

    字符串操作

    下面的函数来自于strings包 这里只介绍一些常用的函数 更加详细的介绍请参考Go语言的官方文档

    Contains

    函数原型如下

    func Contains(s, substr string) bool
    
    • 1

    功能: 字符串s中是否包含substr 返回一个bool值 如果存在返回true 如果不存在返回false

    值得注意的一点是空串在任意字符串中都存在

    Join

    函数原型如下

    func Join(a []string, sep string) string
    
    • 1

    功能: 将切片a中的所有string通过sep链接起来 最后返回我们一个链接完毕的string

    演示代码和效果如下

    a := [] string{"foo" , "bar" , "baz"}
    fmt.Println(strings.Join(s, ", "))
    // 最后输出结果是 foo,bar,baz
    
    • 1
    • 2
    • 3
    index

    函数原型如下

    func Index(s, sep string) int
    
    • 1

    功能: 在字符串s中寻找sep的位置 找到返回位置值 找不到返回-1

    	fmt.Println(strings.Index("chicken", "ken")) // 4
    	fmt.Println(strings.Index("chicken", "dmr")) // -1
    
    • 1
    • 2
    repeat

    函数原型如下

    func Repeat(s string, count int) string
    
    • 1

    功能:重复字符串s n次 并且返回重复后的字符串

    代码示例如下

    	fmt.Println("ba" + strings.Repeat("na", 2)) // banana
    
    • 1
    Replace

    函数原型如下

    func Replace(s, old, new string, n int) string
    
    • 1

    功能:把s字符串中old字符串替换为new字符串 n表示替换的次数 如果n小于0 则表示全部替换

    	var s string = "oink oink oink"
    
    	fmt.Println(strings.Replace(s, "k", "ky", 2))     // oinky  oinky  oink
    	fmt.Println(strings.Replace(s, "oink", "oi", -1)) // oi  oi  oi
    
    • 1
    • 2
    • 3
    • 4
    Split

    函数原型如下

    func Split(s, sep string) []string
    
    • 1

    功能: 把s字符串按照sep切割 最后返回一个切片

    	fmt.Printf("%q\n", strings.Split("hello aa dasdasd dasdax3w", " ")) // ["hello" "aa" "dasdasd" "dasdax3w"]
    	fmt.Printf("%q", strings.Split(" xyz ", "")) // [" " "x" "y" "z" " "]    
    
    • 1
    • 2
    Trim

    函数原型如下

    func Trim(s string, cutset string) string
    
    • 1

    功能: 在s字符串的头部和尾部去除cutset字符串

    	fmt.Println(strings.Trim("!!!    hello world @!!!!!!", " !@"))  // hello world
    
    • 1
    Fields

    函数原型如下

    func Fields(s string) []string
    
    • 1

    功能:去除s字符串的空格符,并且按照空格分割返回切片

    func main() {
    	fmt.Printf("%q", strings.Fields("str     abc     adw"))  // str abc adw
    }
    
    • 1
    • 2
    • 3

    字符串转换

    字符串转换函数在包 strconv 中 如下 我们也只是列出一些常用的函数

    Append

    append系列函数将各种类型转化为字符串之后 添加到现有的字符数组中

    下面是示例代码

    	str := make([]byte, 0, 100) // 创建一个长度为0的byte切片 预留长度大小为100
    
    	str = strconv.AppendInt(str, 1234, 10) // 以10进制的方式往后添加1234
    	str = strconv.AppendBool(str, false)
    	str = strconv.AppendQuote(str, "hello world")
    	str = strconv.AppendQuoteRune(str, '单')
    	fmt.Println(string(str)) // 最后结果是1234false"hello world"'单'
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    Format

    format系列函数将其他类型转化为字符串

    代码演示如下

    	a := strconv.FormatInt(1234, 10) // 将1234 以10进制的方式转化为字符串
    	b := strconv.FormatBool(false)   // 讲false转化为字符串
    	c := strconv.Itoa(1022)
    
    	fmt.Println(a, b, c) // 1234 false 1022
    
    • 1
    • 2
    • 3
    • 4
    • 5
    Parse

    parse系列函数将字符串转化为其他类型 但是转化的过程中有可能会失败 所以说我们要用一个err来接受看看是否转化失败 如果转化失败了 我们可以使用一个函数将其打印出来

    func checkError(e error) {
    	if (e != nil) {
    		fmt.Println(e)
    	}
    }
    
    func main() { 
    	a , err := strconv.ParseInt("1234" , 10 , 64) // 将字符串1234 以10进制的方式转化为64位大小的int类型数据1234
    	checkError(err)  
    	fmt.Println(a)
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    正则表达式

    正则表达式是一个较为庞大的内容 以后会单独开一篇博客来解释 此处就不过多赘述

    Json处理

    JSON是一种比XML更加轻量级的数据交换格式 在易于人们阅读和编写的同时也易于程序的编译和运行 尽管JSON是JavaScript的一个子集 但是json采用完全独立于编程语言的文本格式 并且表现为 键值对集合的文本描述形式 (类似于字典结构 ) 这使他成为一个跨平台 跨语言的数据交换语言

    原来的信息如下

    char name = "小明";
    int age = 18;
    float score[3] = {88.5, 99, 58};
    
    • 1
    • 2
    • 3

    转变为json存储之后如下

       {
            "姓名" : "小明",
            "年龄" : 18,
            "成绩" : [88.5, 99, 58]
       }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    json存储实际上是将原来的数据变成了一个字符串 (也就是说上面的代码实际上就是一个字符串)

    json 数据类型:对象,数组,字符串,数字 介绍如下

    • 对象:使用花括号 {} 括起来的表示一个对象。
    • 字符串:使用常规双引号 “” 括起来的表示一个字符串
    • 数字:包括整形和浮点型,直接使用。
    • 数组:使用中括号 [] 括起来的表示一个数组。

    也就是说 如果我们有多组同类型的数据 我们可以使用数组组织起来

    代码表示如下

    [
       {
            "姓名" : "小明",
            "年龄" : 18,
            "成绩" : [88.5, 99, 58]
       },
       {
            "姓名" : "小黑",
            "年龄" : 18,
            "成绩" : [88.5, 99, 58]
       }
    ]
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    编码Json

    通过结构体生产Json

    使用json.Marshal()函数可以对一组数据进行json格式的编码 函数原型如下

    func Marshal(v interface{}) ([]byte, error)
    
    • 1

    还有一个格式化输出

    func MarshalIndent(v interface{}, prefix, indent string) ([]byte, error
    
    • 1

    示例代码如下

    	t1 := IT{"itcast", []string{"Go", "C++"}, true, 666.66}
    
    	// 下面生成一段json格式的文本
    	b, err := json.Marshal(t1)
    	// 如果成功 则err将会是空 b将会是一段json格式的文本  // {"Company":"itcast","Subjects":["Go","C++"],"IsOK":true,"Price":666.66}
    	if err == nil {
    		fmt.Println(string(b))
    	} else {
    		fmt.Println("error!!!!")
    		fmt.Println(err)
    	}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    json.MarshalIndent 函数是 Go 语言中用于将数据结构转换为带有缩进格式的 JSON 字符串的函数。它提供了更易读的输出格式,便于阅读和调试。

    func MarshalIndent(v interface{}, prefix, indent string) ([]byte, error)
    
    • 1

    这里主要介绍下prefix 和 indent参数

    • prefix 每行的前缀 如果我们将其赋值为 “hello” 那么以后每一行都会先打印一个hello
    • indent 表示缩进的大小 我们一般使用空字符串来进行缩进

    下面是缩进后的格式

    在这里插入图片描述

    struct tag

    我们可以看到上面的输出字段首字母都是大写的 那如果我们想要首字母小写怎么办呢 将结构体中的标识符修改为小写嘛

    可是当我们将结构体中的标识符修改为小写之后我们发现json 不输出该字段

    所以说我们写Json的时候需要注意 只有当导出字段的首字母是大写才会输出 如果我们修改字段为小写 就会发现该字段不会输出了

    所以说我们必须要定义struct tag来实现

    在Go语言中 结构体字段可以通过 tag 来进行注释和元数据的添加 它位于字段的后方 并且被反引号包围

    我们的定义struct tag的时候需要注意的几点是

    • 字段的tag是"-",那么这个字段不会输出到JSON
    • tag中带有自定义名称,那么这个自定义名称会出现在JSON的字段名中
    • tag中如果带有"omitempty"选项,那么如果该字段值为空,就不会输出到JSON串中
    • 如果字段类型是bool, string, int, int64等,而tag中带有",string"选项,那么这个字段在输出到JSON的时候会把该字段对应的值转换成JSON字符串
    type IT struct {
    	Company  string   `json:"-"`        // 这里表示company不会出现在Json中
    	Subjects []string `json:"subjects"` // 这里对于Subjiects重新命名了 所以说在最后会显示subjects
    	IsOK     bool     `json:",string"`  // 先转化为字符串再输出
    	Price    float64  `json:omitempty`  // 如果Price为空 就不输出
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    最后结果如下
    在这里插入图片描述

    通过map生产json
    func main() {
    	t1 := make(map[string]interface{})
    
    	t1["k1"] = true
    	t1["k2"] = 1234
    	t1["k3"] = "hello world"
    
    	b, err := json.MarshalIndent(t1, "", "  ")
    
    	if err == nil {
    		fmt.Println(string(b))
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    生产结果如下

    {                    
      "k1": true,        
      "k2": 1234,        
      "k3": "hello world"
    }      
    
    • 1
    • 2
    • 3
    • 4
    • 5

    解码Json

    可以使用json.Unmarshal()函数将JSON格式的文本解码为Go里面预期的数据结构

    json.Unmarshal()函数的原型如下

    func Unmarshal(data []byte, v interface{}) error
    
    • 1

    该函数的第一参数是json格式的文本( 字节序列 ) 第二个参数是目标输出容器 用于存放转化后的值

    解析到结构体

    代码演示如下 其实就是调用了下Unmarshal函数 此外并无其他难点

    	t1 := IT{"itcast", []string{"Go", "C++"}, true, 666.66}
    	b, err := json.MarshalIndent(t1, "", "  ")
    
    	if err == nil {
    		fmt.Println(string(b))
    	}
    
    	var t2 IT
    	err = json.Unmarshal(b, &t2)
    
    	if err == nil {
    		fmt.Println(t2)
    	}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    解析到interface

    演示代码如下

    func main() {
    	t1 := IT{"itcast", []string{"Go", "C++"}, true, 666.66}
    	b, err := json.MarshalIndent(t1, "", "  ")
    
    	if err == nil {
    		fmt.Println(string(b))
    	}
    
    	var t interface{}
    	err = json.Unmarshal(b, &t)
    
    	m, ok := t.(map[string]interface{})
    
    	if ok == true {
    		for k, v := range m {
    			fmt.Println(k, v)
    		}
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    上面代码的逻辑也很简单 我们使用了一个任意类型t来接受 json中的格式

    最后我们使用一个类型断言来判断t的类型 如果断言成功 那么我们的m就会变成 map[string]interface{} 之后我们对于该类型进行遍历即可

    文件操作

    相关api介绍

    建立和打开文件

    建立文件

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

    func Create(name string) (file *File, err Error)
    
    • 1

    上面的函数会根据文件名创建一个新的文件 返回一个文件对象 创建文件的默认权限为0666 如果说对于权限不理解的同学可以参考我的这篇博客 Linux权限

    返回的文件对象是可读写的

    func NewFile(fd uintptr, name string) *File
    
    • 1

    根据文件描述符创建文件 返回一个文件对象

    打开文件

    我们可以通过下面两种方式打开一个文件

    func Open(name string) (file *File, err Error)
    
    • 1

    我们可以通过Open函数+文件名的方式打开一个文件 但是此时的权限会变为只读 内部实现其实调用了Openfile

    func OpenFile(name string, flag int, perm uint32) (file *File, err Error)
    
    • 1

    打开名称为name的文件 flag是打开方式 如只读 只写等 perm是权限

    这里需要注意的是 如果文件已经创建 那么perm只能截断权限 而不能扩大权限

    关闭文件
    func (file *File) Close() 
    
    • 1
    写文件

    写文件主要是通过下面几个函数实现

    func (file *File) Write(b []byte) (n int, err Error)                   // 写入byte类型的数据到文件 
    func (file *File) WriteAt(b []byte, off int64) (n int, err Error)      // 从 off位置开始写入byte类型的数据到文件
    func (file *File) WriteString(s string) (ret int, err Error)           // 写入string类型的数据到文件 
    
    • 1
    • 2
    • 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中 
    
    • 1
    • 2
    删除文件
    func Remove(name string) Error     // 调用函数就是删除名字为string的文件
    
    • 1

    示例代码

    写文件
    func main() {
    	fout, err := os.Create("test.txt")
    
    	if err != nil {
    		fmt.Println(err)
    	} // error
    
    	defer fout.Close() // main函数结束前关闭文件
    
    	for i := 0; i < 5; i++ {
    		outstr := fmt.Sprintf("%s : %d\n", "hello go", i)
    		fout.WriteString(outstr)
    		fout.Write([]byte("abcd\n"))
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    上面这段代码运行完毕之后我们就会在当前路径下创建一个 test.txt 文档 文档内容如下

    在这里插入图片描述

    读文件
    	fin, err := os.Open("test.txt")
    
    	if err != nil {
    		fmt.Println(err)
    	} // error
    
    	defer fin.Close()
    
    	b1 := make([]byte, 100, 200)
    
    	fin.Read(b1)
    
    	fmt.Println(string(b1))
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    拷贝文件

    需求如下

    • 用户使用程序时输入两个命令行参数
    • 我们规定 第一个是源文件 第二个是拷贝文件
    • 我们要将源文件中的数据全部拷贝到拷贝文件中

    代码表示如下

    func main() {
    	args := os.Args
    
    	if args == nil || len(args) < 2 {
    		fmt.Println("error ! need more para")
    		return
    	}
    
    	src := args[1]
    	desc := args[2]
    
    	// fmt.Println(src, desc)
    	fmt.Println(src, desc)
    	fout, err1 := os.Open(src)
    
    	// 下面的代码作用是打开两个文件
    	if err1 != nil {
    		fmt.Println(err1)
    		return
    	}
    
    	defer fout.Close()
    
    	// 这里无法写入是因为Open打开文件是只读
    	// fin, err2 := os.Open(desc)
    	fin, err2 := os.OpenFile(desc, os.O_WRONLY, 0666)
    
    	if err2 != nil {
    		fmt.Println(err2)
    		return
    	}
    
    	defer fin.Close()
    
    	b1 := make([]byte, 100, 200)
    	n, _ := fout.Read(b1)
    	fin.Write(b1[:n])
    
    	fmt.Println("程序运行成功")
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40

    如何在IDE中设置命令行参数

    我们可以右键文件 选择修改文件配置选项

    在这里插入图片描述

    之后在程序实参中选择即可 注意 不需要加 -

  • 相关阅读:
    QA新人任务成果演示
    猿创征文|我的前端学习之旅【来自一名大四老学长的真情流露】
    幸存者偏差
    开发者也能“搞艺术”?聚合数据联合科大讯飞助力开发者创新不断
    三层交换机与防火墙对接上网如何配置
    css四种导入方式
    harbor安装
    精品基于ssm的足球联赛管理系统的设计与实现vue
    面试题之MyBatis缓存
    express promise async await promisify
  • 原文地址:https://blog.csdn.net/meihaoshy/article/details/134496260