golang学习八: 文件操作:字符串的处理, 字符串的类型转换, 文件操作

Golang学习 专栏收录该内容
20 篇文章 2 订阅

一、字符串的处理:

1. strings包:

从文件中将数据读取出来后,很多情况下并不是将数据打印出来, 而是要做相对应的处理. 例如: 去掉空格等一些特殊符号, 对一些内容进行替换等;
这里涉及到对一些字符串的处理, 需要借助于包"strings"

  • 常用的字符串处理函数:
    • Contains;
    • Join:
    • Index;
    • Repeat;
    • Replace
    • Split;
    • Trim;
    • Fields;

2. Contains是否包含:

语法:

func Contains(s, substr string) bool

功能:字符串s中是否包含substr,返回bool值

import (
	"fmt"
	"strings"
)

func main() {
	str1 := "hello world"
	str2 := "h"

	// Contains(被查找的字符串, 查找的字符串)	返回值: bool
	// 一般用于模糊查找
	b := strings.Contains(str1, str2)
	fmt.Println(b) // true
}

3. Join: 字符串连接

语法:

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

功能:字符串链接,把slicea通过sep链接起来

func main() {
	// 字符串切片
	slice := []string{"123", "abc", "456"}

	// Join(切片, "分隔符")
	str1 := strings.Join(slice, ",")
	fmt.Println(str1)	// 123,abc,456
}

4. Index查找索引

语法:

func Index(s, substr string) int

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

func main() {
	str1 := "hello world"
	str2 := "g"
	str3 := "h"

	// Index(要查找的字符串, 查找内容): 查找一个字符串在另一个字符串中第一次出现的位置, 返回值: int下标; -1表示找不到
	i1 := strings.Index(str1, str2)
	fmt.Println(i1) // -1

	i2 := strings.Index(str1, str3)
	fmt.Println(i2) // 0
}

5. Repeat: 重复

语法:

func Repeat(s string, count int) string

功能:重复s字符串count次,最后返回重复的字符串

func main() {
	str := "hello world..."
	// 将一个字符串重复n次
	str1 := strings.Repeat(str, 5)
	fmt.Println(str1)	// hello world...hello world...hello world...hello world...hello world...
}

6. Replace:替换:

语法:

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

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

func main() {
	str := "一些敏感的词汇的敏感"

	// 字符串替换, 屏蔽敏感词汇
	str1 := strings.Replace(str, "敏感", "**", 1)
	fmt.Println(str1) // 一些**的词汇的敏感

	// 如果替换次数小于0, 则表示全部替换
	str2 := strings.Replace(str, "敏感", "**", -1)
	fmt.Println(str2) // 一些**的词汇的**
}

7. Split: 分割

语法:

func Split(s, sep string) []string

功能:把s字符串按照sep分割,返回slice

func main() {
	str1 := "130-188-1999"

	// 切割字符串
	slice := strings.Split(str1, "-")
	fmt.Println(slice)	// [130 188 1999]
}

8. Trim: 去除指定的字符串

语法:

func Trim(s string, cutset string) string

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

func main() {
	str := "===are===U===OK==="
	// Trim: 去掉字符串指定的首位内容
	str1 := strings.Trim(str, "=")
	fmt.Println(str1)	// are===U===OK
}

9. Fields: 去除空格

语法:

func Fields(s string) []string

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

func main() {
	str := "  are  U  ok  "

	// 去掉头尾的空格, 一般用于统计单词个数
	slice := strings.Fields(str)
	fmt.Println(slice)	// [are U ok]
}

二、字符串的类型转换:

1. strconv包:

GO语言也提供了字符串与其它类型之间相互转换的函数; 相应的字符串转换函数都在"strconv"包

  • 字符串转换:
    • Format;
    • Parse;
    • Append;

2. 字符串转字符切片:

func main() {
	str := "hello world"
	// 将字符串转成字符切片 => 强制类型转换
	slice := []byte(str)

	fmt.Println(slice) // [104 101 108 108 111 32 119 111 114 108 100]
}

3. Format: 把其他类型的转换为字符串

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

func main() {
	// 字符串切片
	slice := []byte{'h', 'e', 'l', 'l', 'o', 97}
	fmt.Println(slice)         // [104 101 108 108 111 97]
	fmt.Println(string(slice)) // helloa

	// 将其他类型转换成字符串
	b := false
	str1 := strconv.FormatBool(b)
	fmt.Println(str1)        // false
	fmt.Printf("%T\n", str1) // string

	str2 := strconv.FormatInt(140, 16) // 第二个参数是要转化的进制(2, 8, 10, 16)
	fmt.Println(str2)                  // 8c
	fmt.Printf("%T\n", str2)           // string

	str3 := strconv.FormatFloat(3.141592, 'f', 4, 64)
	fmt.Println(str3)        // 3.1416
	fmt.Printf("%T\n", str3) // string

	str4 := strconv.Itoa(123)
	fmt.Println(str4)	// 123
}

3. Parse: 把字符串转换为其他类型:

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


func main() {
	// 将字符串转成其他类型
	b1, err1 := strconv.ParseBool("true")
	fmt.Println(b1, err1)  // true <nil>
	fmt.Printf("%T\n", b1) // bool

	// 转换失败 返回false
	b2, err2 := strconv.ParseBool("truee")
	fmt.Println(b2, err2)  // false strconv.ParseBool: parsing "truee": invalid syntax
	fmt.Printf("%T\n", b2) // bool

	v1, err3 := strconv.ParseInt("abc", 16, 64)
	fmt.Println(v1, err3)  // 2748 <nil>
	fmt.Printf("%T\n", v1) // int64

	v2, err4 := strconv.ParseFloat("3.14159", 64)
	fmt.Println(v2, err4)  // 3.14159 <nil>
	fmt.Printf("%T\n", v2) // float64
}

4. Append:

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

func main() {
	// 将其他类型转成字符串, 并且添加到字符切片里
	slice := make([]byte, 0, 1024)

	slice = strconv.AppendBool(slice, false)
	slice = strconv.AppendInt(slice, 123, 2)
	slice = strconv.AppendFloat(slice, 3.14159, 'f', 4, 64)
	slice = strconv.AppendQuote(slice, "hello")
	fmt.Println(slice, string(slice))
	// [102 97 108 115 101 49 49 49 49 48 49 49 51 46 49 52 49 54 34 104 101 108 108 111 34] false11110113.1416"hello"
}

三、文件操作:

1. 新建文件:

将数据存储到文件之前, 先要创建文件. GO语言中提供了一个Create()函数专门创建文件.
该函数在创建文件时, 首先会判断要创建的文件是否存在, 如果不存在, 则创建, 如果存在, 会先将文件中已有的数据清空;
同时, 当文件创建成功后, 该文件会默认的打开, 所以不用在执行打开操作, 可以直接向该文件中写入数据;

  • 创建文件的步骤:
    • 导入"os"包, 创建文件, 读写文件的函数都在该包;
    • 指定创建的文件存放路径以及文件名;
    • 执行Create()函数, 进行文件创建;
    • 关闭文件;
package main

import (
	"fmt"
	"os"
)

func main() {
	// 返回值 => 文件指针 和 错误信息
	fp, err := os.Create("./a.txt")
	if err != nil {
		//文件创建失败
		/*
		   1.路径不存在
		   2.文件权限
		   3.程序打开文件上限
		*/
		fmt.Println("文件创建失败")
		return
	}

	// todo: 读写文件

	//关闭文件
	//如果打开文件不关闭 造成内存的浪费  程序打开文件的上限
	//fp.Close()
	defer fp.Close()
}

2. 写入文件:

文件打开以后, 可以向文件中写数据, 可以使用WriteString()方法

package main

import (
	"fmt"
	"os"
)

func main() {
	//\反斜杠 转义字符
	//在写路径时可以使用/正斜杠代替\反斜杠
	fp, err := os.Create("./a.txt")
	if err != nil {
		fmt.Println("文件创建失败")
		return
	}

	// TODO: 写文件
	// \n不会换行  原因 在windows文本文件中换行\r\n  回车  在linux中换行\n
	fp.WriteString("hello world...\r\n")
	fp.WriteString("123456789...\r\n")

	defer fp.Close()
}
func main() {
	fp, err := os.Create("./a.txt")
	if err != nil {
		fmt.Println("文件创建失败")
		return
	}

	// TODO: 写文件
	// slice := []byte{'h', 'e', 'l', 'l', 'o'}
	// count, err := fp.Write(slice)	// 5
	count, err := fp.Write([]byte("好好学习, 天天向上")) // 26
	if err != nil {
		fmt.Println("写入文件失败")
		return
	} else {
		fmt.Println(count)
	}

	defer fp.Close()
}
func main() {
	fp, err := os.Create("./a.txt")
	if err != nil {
		fmt.Println("文件创建失败")
		return
	}

	// TODO: 写文件
	// 获取光标流位置
	// 获取文件起始位置到结尾有多少字符
	count, _ := fp.Seek(0, os.SEEK_END) // os.SEEK_END: 后续版本会取消
	fmt.Println(count)

	count1, _ := fp.Seek(0, io.SeekEnd)
	fmt.Println(count1) // 0

	// 按照指定位置写入
	// func (f *File) WriteAt(b []byte, off int64) (n int, err error)
	fp.WriteAt([]byte("hello world"), count1)
	fp.WriteAt([]byte("哈"), 0) // 内容被覆盖了
	fp.WriteAt([]byte("真香"), 19)

	defer fp.Close()
}

3. 打开文件:

// os.Open() 只支持读操作, 不能进行写入操作
fp, err := os.Open("./a.txt")
func OpenFile(name string, flag int, perm FileMode) (*File, error)

说明:

  • OpenFile( )这个函数有三个参数,第一个参数表示打开文件的路径,第二个参数表示模式,常见的模式有:
    • O_RDONLY: 只读模式;
    • O_WRONLY: 只写模式;
    • O_RDWR: 可读可写模式;
    • O_APPEND: 追加模式;
  • 第三个参数, 表示权限, 取值范围(0-7)表示如下:
说明
0没有任何权限
1执行权限(如果是可执行文件, 是可以运行的)
2写权限
3写权限与执行权限
4读权限
5读权限与执行权限
6读权限与写权限
7读权限, 写权限, 执行权限
func main() {
	// 打开存在的文件
	// os.Open() 只支持读操作
	// fp, err := os.Open("./a.txt")

	// func OpenFile(name string, flag int, perm FileMode) (*File, error)

	fp, err := os.OpenFile("./a.txt", os.O_RDWR, 6)
	if err != nil {
		fmt.Println("打开文件失败...")
		return
	}

	// fp.WriteString("好好学习\r\n")
	fp.WriteAt([]byte("hahahah"), 30)

	defer fp.Close()
}

4. 读取文件内容:

Read 读取文件
如果文件已经存在, 并且也已经有数据了, 那么可以直接读取该文件中的内容;
读取文件的基本流程如下:

  • 打开要读取的文件;
  • 对文件进行读取;
  • 关闭文件;
package main

import (
    "fmt"
    "io"
    "os"
)
func main() {
    //打开文件
    fp, err := os.Open("D:/a.txt")
    if err != nil {
        fmt.Println("err=", err)
        return
    }

    buf := make([]byte, 1024*2) //2k大小
    //n代表从文件读取内容的长度
    n, err1 := fp.Read(buf)
    // io.EOF: 指文件的末尾
    if err1 != nil && err1 != io.EOF {
        fmt.Println("err1=", err1)
        return
    }
    fmt.Println("buf=", string(buf[:n]))

    //关闭文件
    defer fp.Close()
}

按行读取:

方式一:

package main

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

func main() {
	fp, err := os.Open("./a.txt")
	if err != nil {
		fmt.Println("err=", err)
		return
	}

	// 创建缓冲区
	r := bufio.NewReader(fp)
	// 行读取, 截取的标志 '\n'
	slice, _ := r.ReadBytes('\n')
	fmt.Println(string(slice))
	slice, _ = r.ReadBytes('\n')
	fmt.Println(string(slice))

	for {
		// 遇到\n就结束读取, 但是\n也需要读取
		buf, err1 := r.ReadBytes('\n')
		if err1 != nil || err1 == io.EOF {
			fmt.Println("error = ", err1)
			break
		}
		fmt.Println(string(buf))
	}

	//关闭文件
	defer fp.Close()
}

方式二: 直接读取字符串

func main() {
	fp, err := os.Open("./a.txt")
	if err != nil {
		fmt.Println("err=", err)
		return
	}

	// 创建缓冲区
	r := bufio.NewReader(fp)
	// 行读取, 截取的标志 '\n'
	slice, _ := r.ReadBytes('\n')
	fmt.Println(string(slice))
	slice, _ = r.ReadBytes('\n')
	fmt.Println(string(slice))

	for {
		str, err1 := r.ReadString('\n')
		if err1 != nil && err1 == io.EOF {
			fmt.Println("error = ", err1)
			break
		}
		fmt.Println(str)

	}
	//关闭文件
	defer fp.Close()
}

5. 文件操作案例:

文件拷贝,将已有的文件复制一份,同时重新命名。
基本的思路:

  • 让用户输入要拷贝的文件的名称(源文件)以及目的文件的名称;
  • 创建目的文件;
  • 打开源文件,并且读取该文件中的内容;
  • 将从源文件中读取的内容写到目的文件中;
package main

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

func main() {
	var srcFilename string
	var dstFilename string

	fmt.Println("请输入原文件名称:")
	fmt.Scan(&srcFilename)
	fmt.Println("请输入目的文件名称:")
	fmt.Scan(&dstFilename)

	// 打开文件
	fp, err := os.Open(srcFilename)
	fd, err1 := os.Create(dstFilename)
	if err != nil || err1 != nil {
		fmt.Println("打开文件失败...")
		return
	}
	//核心处理,从源文件读取内容,往目的文件写,读多少写多少
	buf := make([]byte, 4*1024) //4k大小临时缓冲区
	for {
		n, err := fp.Read(buf)           //从源文件读取内容,每次读取一部分
		if err != nil || err == io.EOF { //文件读取完毕
			break
		}
		//往目的文件写,读多少写多少
		fd.Write(buf[:n])
	}
	// 关闭文件
	defer fp.Close()
	defer fd.Close()
}

  • 0
    点赞
  • 0
    评论
  • 1
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

©️2021 CSDN 皮肤主题: 技术黑板 设计师:CSDN官方博客 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值