Golang学习笔记(9)

十四章 文件操作

基本介绍

文件.对我们并不陌生文件是数据源(保存数据的地方)的一种,比如大家经常使用的word文档.txt文件,excl文件.都是文件。文件最主要的作用就是保存数据.它既可以保存一张图片.也可以保持视频,声音…
在这里插入图片描述

  • os.File封装所有文件相关操作,File是一个结构体。

常用的文件操作函数和方法

  1. 打开一个文件进行读操作:
    os.Open(name string)(*File,error)
  2. 关闭一个文件:
    File.Close()
package main

import (
	"fmt"
	"os"
)

func main() {
	//打开一个文件
	//概念说明:file的叫法
	//1、file对象
	//2、file指针
	//3、file文件句柄
	file, err := os.Open("d:/text.txt")
	if err != nil {
		fmt.Println("open file err=", err)
	}
	fmt.Printf("file=%v\n", file)
	//关闭文件
	err = file.Close()
	if err != nil {
		fmt.Println("close file err=", err)
	}

}

在这里插入图片描述

  1. 其它方法和函数

读文件操作应用实例

  1. 读取文件的内容并显示在终端(带缓冲区的方式),使用os.Open,fle.Close,bufio.NewReader(),reader…ReadString函数和方法
package main

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

func main() {
	//打开一个文件
	//概念说明:file的叫法
	//1、file对象
	//2、file指针
	//3、file文件句柄
	file, err := os.Open("d:/test.txt")
	if err != nil {
		fmt.Println("open file err=", err)
	}
	//当函数退出时,要及时关闭file
	defer file.Close() //及时关闭,避免内存泄漏

	//创建一个*Reader,带缓冲的
	/*
		const(
		defaultBufferSize = 4096 //默认缓冲区为4096
		)
	*/
	reader := bufio.NewReader(file)
	for {
		str, err := reader.ReadString('\n') //每读到一个换行就结束
		if err == io.EOF {                  //表示文件的末尾
			break
		}
		//输出内容
		fmt.Print(str)
	}
	fmt.Println("文件读取结束")
}

  1. 读取文件的内容并显示在终端(使用0ut一次将整个文件读入到内存中),这种方式适用于文件不大的情况。相关方法和函数(ioutil.ReadFile)
package main

import (
	"fmt"
	"os"
)

func main() {
	//使用os.ReadFile一次性将文件读取到位
	file := "d:/test.txt"
	content, err := os.ReadFile(file)
	if err != nil {
		fmt.Printf("read error: %v\n", err)
	}
	//把读取到的内容显示到终端
	fmt.Printf("%v\n", content)
	fmt.Printf("%v\n", string(content))
	//我们没有显式的Open文件,因此不需要显式的close文件
	//因为,文件的open和close被封装到ReadFile函数内部
}

写文件操作的应用实例

基本介绍

func OpenFile(name string,flag int,perm FileMode)(file #File,err error)
说明:os.OpenFile是一个更一般性的文件打开函数,它会使用指定的选项(如O RDONLY等),指定的模式(如0666等)打开指定名称的文件。如果操作成功,返回的文件对象可用于I/O。如果出错,错误底层类型是*PathError。
在这里插入图片描述
第二个参数:文件打开模式(可以组合):
在这里插入图片描述
第三个参数:权限控制(linux)
在这里插入图片描述

基本应用实例 - 方式一

1)创建一个新文件,写入内容5句"hello,Gardon"

package main

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

func main() {
	//创建一个新文件,写入内容5句"hello,Gardon"
	filePath := "d:/abc.txt"
	file, err := os.OpenFile(filePath, os.O_WRONLY|os.O_CREATE, 0666)
	if err != nil {
		fmt.Printf("Error opening file = %v", err)
		return
	}
	// 及时关闭file句柄,防止泄露
	defer file.Close()
	str := "hello,Gardon\n"
	//写入时,使用带缓存的writer
	writer := bufio.NewWriter(file)
	for i := 0; i < 5; i++ {
		writer.WriteString(str)
	}
	//因为在调用WriteString方法时,内容是先写入到
	//所以需要调用FlUsh方法,将缓冲的数据真正写入到文件中,否则没有数据
	writer.Flush()
}

在这里插入图片描述

2)打开一个存在的文件中,将原来的内容覆盖成新的内容10句"你好,尚硅谷!"

package main

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

func main() {
	//创建一个新文件,写入内容5句"hello,Gardon"
	//打开一个已经存在的文件
	filePath := "d:/abc.txt"
	file, err := os.OpenFile(filePath, os.O_WRONLY|os.O_TRUNC, 0666)
	if err != nil {
		fmt.Printf("Error opening file = %v", err)
		return
	}
	// 及时关闭file句柄,防止泄露
	defer file.Close()
	str := "你好,GO!\n"
	//写入时,使用带缓存的writer
	writer := bufio.NewWriter(file)
	for i := 0; i < 10; i++ {
		writer.WriteString(str)
	}
	//因为在调用WriteString方法时,内容是先写入到
	//所以需要调用FlUsh方法,将缓冲的数据真正写入到文件中,否则没有数据
	writer.Flush()
}

在这里插入图片描述

3)打开一个存在的文件,在原来的内容追加内容’ABC!ENGLISH!"

package main

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

func main() {
	//打开一个已经存在的文件
	filePath := "d:/abc.txt"
	file, err := os.OpenFile(filePath, os.O_WRONLY|os.O_APPEND, 0666)
	if err != nil {
		fmt.Printf("Error opening file = %v", err)
		return
	}
	// 及时关闭file句柄,防止泄露
	defer file.Close()
	str := "ABC!ENGLISH!\n"
	//写入时,使用带缓存的writer
	writer := bufio.NewWriter(file)
	for i := 0; i < 1; i++ {
		writer.WriteString(str)
	}
	//因为在调用WriteString方法时,内容是先写入到
	//所以需要调用FlUsh方法,将缓冲的数据真正写入到文件中,否则没有数据
	writer.Flush()
}

在这里插入图片描述

4)打开一个存在的文件,将原来的内容读出显示在终端,并且追加5句"hello,北京!"

package main

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

func main() {
	//打开一个已经存在的文件
	filePath := "d:/abc.txt"
	file, err := os.OpenFile(filePath, os.O_RDWR|os.O_APPEND, 0666)
	if err != nil {
		fmt.Printf("Error opening file = %v", err)
		return
	}
	// 及时关闭file句柄,防止泄露
	defer file.Close()
	//先读取原来文件的内容,并且显示在终端
	reader := bufio.NewReader(file)
	for {
		str, err := reader.ReadString('\n')
		if err == io.EOF {
			break
		}
		//显示到终端
		fmt.Print(str)
	}
	//写入新内容
	str := "Hello,中国!\n"
	//写入时,使用带缓存的writer
	writer := bufio.NewWriter(file)
	for i := 0; i < 5; i++ {
		writer.WriteString(str)
	}
	//因为在调用WriteString方法时,内容是先写入到
	//所以需要调用FlUsh方法,将缓冲的数据真正写入到文件中,否则没有数据
	writer.Flush()
}

在这里插入图片描述

使用os.OpenFile(),bufio.NewWriter(),*Writer的方法WriteString完成上面的任务.

基本应用实例 - 方式二

编程一个程序,将一个文件的内容,写入到另外一个文件。注:这两个文件已经存在了。
说明:使用os.ReadFile()/os.WriteFile()完成写文件的任务

package main

import (
	"fmt"
	"os"
)

func main() {
	//将d:/abc.txt文件内容导入到e:/kkk.txt
	//首先将d:/abc.txt内容读取到内存
	//将读取到的内容写入e:/kkk.txt
	file1Path := "d:/abc.txt"
	file2Path := "e:/kkk.txt"
	data, err := os.ReadFile(file1Path)
	if err != nil {
		//说明读取文件错误
		fmt.Printf("read file err =%v\n", err)
		return
	}
	err = os.WriteFile(file2Path, data, 0666)
	if err != nil {
		fmt.Printf("write file err =%v\n", err)
	}
}

判断文件是否存在

golang判断文件或文件夹是否存在的方法为使用os.Stat()函数返回的错误值进行判断:

  1. 如果返回的错误为il,说明文件或文件夹存在
  2. 如果返回的错误类型使用os.IsNotExist()判断为true,说明文件或文件夹不存在
  3. 如果返回的错误为其它类型,则不确定是否在存在
func PathExists(path string)(bool,error){
	_,err :=os.Stat(path)
	if err == nil{
			return true,nil	
	}
	if os.IsNotExist(err){
			return false,nil
	}
	return false,err
}
package main
import (
	"fmt"
	"os"
)
func main() {
	var fileName = "D:/abcd.txt"
	_, err := os.Stat(fileName)
	if err == nil {
		fmt.Println("File exist")
		return
	}
	if os.IsNotExist(err) {
		fmt.Println("File not exist")
		return
	}
	fmt.Println("File error")
	return
}

package main

import (
	"fmt"
	"os"
)

func PathExists(path string) (bool, error) {
	_, err := os.Stat(path)
	if err == nil {
		fmt.Println("path exists")
		return true, nil
	}
	if os.IsNotExist(err) {
		fmt.Println("path does not exist")
		return false, nil
	}
	return false, err
}
func main() {
	PathExists("D:/abc.txt")

}

文件编程应用实例 - 拷贝文件

说明:将一张图片/电影拷贝到另一个文件下 e:/abc.jpg
Copy函数是由io包提供的
在这里插入图片描述

package main

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

// 编写一个函数,接收两个文件路径 srcFileName dstFileName
func CopyFile(dstFileName string, srcFileName string) (written int64, err error) {
	srcFile, err := os.Open(srcFileName)
	if err != nil {
		fmt.Printf("open file err = %v\n", err)
	}
	defer srcFile.Close()
	//通过srcFile,获取到Reader
	reader := bufio.NewReader(srcFile)
	//打开dstFileName
	dstFile, err := os.OpenFile(dstFileName, os.O_WRONLY|os.O_CREATE, 0666)
	if err != nil {
		fmt.Printf("open file err = %v\n", err)
		return
	}
	writer := bufio.NewWriter(dstFile)
	defer dstFile.Close()
	return io.Copy(writer, reader)
}
func main() {
	//将d:/flower.jpg文件拷贝e:/abc.jpg
	//调用完成文件拷贝
	srcFile := "d:/flower.jpg"
	dstFile := "e:/abc.jpg"
	_, err := CopyFile(dstFile, srcFile)
	if err == nil {
		fmt.Println("Successfully copied")
	} else {
		fmt.Printf("拷贝错误 Error: %v\n", err)
	}
}

统计英文、数字、空格和其它字符数量

说明:统计一个文件中含有的英文、数字、空格及其他字符数量

package main

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

// 定义一个结构体,用于保存统计的结果
type CharCount struct {
	ChCount    int //记录英文个数
	NumCount   int //记录数字个数
	SpaceCount int //记录空格个数
	OtherCount int //记录其他字符
}

func main() {
	//打开一个文件,创建一个reader
	//每读取一行,就去统计该行有多少个英文、数字、空格和其它字符
	//然后将结果保存到一个结构体中
	fileName := "e:/abc.txt"
	file, err := os.Open(fileName)
	if err != nil {
		fmt.Printf("Error opening file,error: %v", err)
		return
	}
	defer file.Close()
	//定义一个CharCount实例
	var count CharCount
	//创建一个reader
	reader := bufio.NewReader(file)
	//循环读取文件内容
	for {
		str, err := reader.ReadString('\n')
		if err == io.EOF {
			break
		}
		//为了兼容中文字符,可以将str转成[]rune
		str = []rune(str)
		//遍历str,进行统计
		for _, v := range str {

			switch {
			case v >= 'a' && v <= 'z':
				fallthrough //穿透
			case v >= 'A' && v <= 'Z':
				count.ChCount++
			case v == ' ' || v == '\t':
				count.SpaceCount++
			case v >= '0' && v <= '9':
				count.NumCount++
			default:
				count.OtherCount++

			}
		}
	}
	//输出统计的结果
	fmt.Printf("字符的个数为=%v 数字的个数为=%v空格的个数为=%v其它字符个数=%v",
		count.ChCount, count.NumCount, count.SpaceCount, count.OtherCount)
}

命令行参数

需求:希望能够获取命令行输入的各种参数。

  • 基本介绍
    os.Args是一个string的切片,用来存储所有的命令行参数。
  • 案例
    请编写一段代码,可以获取命令行各个参数。
package main

import (
	"fmt"
	"os"
)

func main() {
	fmt.Println("命令行的参数有", os.Args)
	//遍历os.Args切片,就可以得到所有命令行的输入参数值
	for i, v := range os.Args {
		fmt.Printf("args[%v] = %v\n", i, v)
	}
}

flag包用来解析命令行参数

说明:前面的方式是比较原生的方式,对解析参数不是特别的方便,特别是带有指定参数形式的命令行
比如:cmd>main.exe -f c:/aaa.txt -p 200 -u root 这样的形式命令行,GO设计者给我们提供了flag包,可以方便的解析命令行参数,而且参数顺序可以随意

  • 案例
  • 编写一段代码,获取命令行各个参数。
package main

import (
	"flag"
	"fmt"
)

func main() {
	//定义变量,用于接收命令行的参数值
	var user string
	var pwd string
	var host string
	var port int
	flag.StringVar(&user, "u", "", "用户名默认为空")
	flag.StringVar(&pwd, "pwd", "", "密码,默认为空")
	flag.StringVar(&host, "h", "localhost", "主机名,默认为localhost")
	flag.IntVar(&port, "port", 3306, "端口号,默认为3306")
	//转换,调用该方法
	flag.Parse()
	//输出结果
	fmt.Printf("user = %v pwd = %v host = %v port = %v",
		user, pwd, host, port)

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值