文件,对我们并不陌生,文件是数据源(保存数据的地方)的一种,比如大家经常使用的word文档, txt 文件,excel文件 … 都是文件.文件最主要的作用就是保存数据,它既可以保存一张图片也可以保存视频,声音...
文件在程序中是以流的形式来操作的
流:数据在数据源(文件)和程序(内存)之间经历的路径
输入流: 数据从数据源(文件)到程序 ( 内存)的路径
输出流: 数据从程序(内存)到数据源(文件)的路径
os.File封装了所有与文件相关的操作,File是一个结构体
- package main
-
- import (
- "fmt"
- "os"
- )
-
- func main() {
- //打开文件(文件是一个指针类型)
- //概念: file叫法: 1. file对象 2.file指针 3.file 文件句柄
- file, err := os.Open("f:/www/test.txt")
-
- if err != nil {
- fmt.Printf("open file err = %v\n", err) //open filt err = %v open f:www/test.txt: The system cannot find the path specified.
- }
-
- //输出文件,可以看出:文件就是一个指针
- fmt.Printf("file=%v\n", file) // 打开文件成功: file=&{0xc000088280}, 打开文件失败:file=<nil>
- //关闭文件
- err = file.Close()
- if err != nil {
- fmt.Println("close file err= %v", err)//close file err= %v invalid argument
- }
- }
(1).读取文件的内容并显示在终端(带缓冲区的方法),使用os.Open,file.Close,bufio.NewReader,reader.ReadString函数和方法
- package main
-
- import (
- "fmt"
- "os"
- "bufio"
- "io"
- )
-
- func main() {
- //打开文件(文件是一个指针类型)
- //概念: file叫法: 1. file对象 2.file指针 3.file 文件句柄
- file, err := os.Open("f:/www/test.txt")
-
- if err != nil {
- fmt.Printf("open file err = %v\n", err) //open filt err = %v open f:www/test.txt: The system cannot find the path specified.
- }
- //当函数退出时,关闭file,避免内存泄漏
- defer file.Close()
- //创建一个 *Reader,是带缓冲的
- /**
- * const (
- * defaultBufSize = 4096 // 默认的缓冲区为4096
- * )
- */
- //NewReader创建一个具有默认大小缓冲、从r读取的*Reader
- reader := bufio.NewReader(file)
- //循环读取文件中的内容
- for {
- str, err := reader.ReadString('\n') //读到一个换行符结束
- if err == io.EOF { //io.EOE 表示文件的末尾
- break
- }
- //输出内容
- fmt.Print(str)
- }
- fmt.Println("文件读取结束")
- }
(2).读取文件的内容并显示在终端(使用ioutil一次性地将整个文件读入到内存中),这种方式适用于文件不大的情况,使用的相关方法和函数:ioutil.ReadFile
- package main
-
- import (
- "fmt"
- "io/ioutil"
- )
-
- func main() {
- //使用io/ioutil.ReadFile一次性将文件读取到位
- file := "f:/www/test.txt"
- //ReadFile 从filename指定的文件中读取数据并返回文件的内容。成功的调用返回的err为nil而非EOF。因为本函数定义为读取整个文件,它不会将读取返回的EOF视为应报告的错误
- content, err := ioutil.ReadFile(file)
- if err != nil {
- fmt.Printf("read file err = %v", err)
- }
- //把读取到文件内容显示到终端
- // fmt.Printf("%v\n", content) //[]byte
-
- fmt.Printf("%v\n", string(content)) //要显示正确的内容,需要把byte切片转换成string
- //没有显示的Open文件,因此也不需要显示的Close文件,因为文件的Open,Close被封装到ReadFile函数内部
- }
第二个参数 flag:文件打开模式(可以组合)参数如下:
第三个参数 perm:权限控制参数如下:
r:读 ===> 4
w:写 ===> 2
x: 执行 ===> 1
- package main
-
- import (
- "fmt"
- "bufio"
- "os"
- )
-
- func main() {
- //创建一个新文件,写入内容:5聚 hello world
- //打开一个文件 "f:/www/test2.txt"
- filePath := "f:/www/test2.txt"
- file, err := os.OpenFile(filePath, os.O_WRONLY | os.O_CREATE, 0666)//O_WRONLY 只写模式打开文件 ,O_CREATE 如果不存在将创建一个新文件,写的方式打开,新增
- if err != nil {
- fmt.Printf("open file err =%v\n", err)
- }
- //及时关闭
- defer file.Close()
- //准备写入5句内容
- content := "hello world\r\n"
- //NewWriter创建一个具有默认大小缓冲、写入w的*Writer
- writer := bufio.NewWriter(file)
- for i := 0; i < 5; i++ {
- //WriteString写入一个字符串。返回写入的字节数。如果返回值nn < len(s),还会返回一个错误说明原因
- writer.WriteString(content)
- }
-
- //因为Writer是带缓冲的,因此在调用WriterString方法时,其实内容是先写入到缓冲的
- //所以需要调用Flush方法,将缓冲中的数据真正写入到文件中,否则文件中会丢失数据
- //Flush方法将缓冲中的数据写入下层的io.Writer接口
- writer.Flush()
- }
- package main
-
- import (
- "fmt"
- "bufio"
- "os"
- )
-
- func main() {
- //打开一个存在的文件,将原来的内容覆盖成新的内容10句:你好,world
- //打开一个存在文件 "f:/www/test2.txt"
- filePath := "f:/www/test2.txt"
- file, err := os.OpenFile(filePath, os.O_WRONLY | os.O_TRUNC, 0666) //O_WRONLY 只写模式打开文件,O_TRUNC 打开时清空文件
- if err != nil {
- fmt.Printf("open file err =%v\n", err)
- }
- //及时关闭
- defer file.Close()
- //准备写入5句内容
- content := "你好,world\r\n"
- writer := bufio.NewWriter(file)
- for i := 0; i < 5; i++ {
- //WriteString写入一个字符串。返回写入的字节数。如果返回值nn < len(s),还会返回一个错误说明原因
- writer.WriteString(content)
- }
-
- //因为Writer是带缓冲的,因此在调用WriterString方法时,其实内容是先写入到缓冲的
- //所以需要调用Flush方法,将缓冲中的数据真正写入到文件中,否则文件中会丢失数据
- //Flush方法将缓冲中的数据写入下层的io.Writer接口
- writer.Flush()
- }
- package main
-
- import (
- "fmt"
- "bufio"
- "os"
- )
-
- func main() {
- //打开一个存在的文件,将原来的内容覆盖成新的内容10句:你好,world
- //打开一个存在文件 "f:/www/test2.txt"
- filePath := "f:/www/test2.txt"
- file, err := os.OpenFile(filePath, os.O_WRONLY | os.O_APPENDC, 0666)//O_WRONLY
- 只写模式打开文件,O_APPENDC 写操作时将数据附加到文件尾部
- if err != nil {
- fmt.Printf("open file err =%v\n", err)
- }
- //及时关闭
- defer file.Close()
- //准备写入5句内容
- content := "你好,world\r\n"
- writer := bufio.NewWriter(file)
- for i := 0; i < 5; i++ {
- writer.WriteString(content)
- }
-
- //因为Writer是带缓冲的,因此在调用WriterString方法时,其实内容是先写入到缓冲的
- //所以需要调用Flush方法,将缓冲中的数据真正写入到文件中,否则文件中会丢失数据
- writer.Flush()
- }
(4).打开一个存在的文件,将原来的内容读出显示在终端,并且追加5句"你好,北京"
- package main
-
- import (
- "fmt"
- "bufio"
- "os"
- "io"
- )
-
- func main() {
- //打开一个存在的文件,将原来的内容读写到终端,并追加内容10句:你好,北京
- //打开一个存在文件 "f:/www/test2.txt"
- filePath := "f:/www/test2.txt"
- file, err := os.OpenFile(filePath, os.O_RDWR | os.O_APPEND, 0666)//O_RDWR 读写模式打开文件, 写操作时将数据附加到文件尾部 O_APPEND
- if err != nil {
- fmt.Printf("open file err =%v\n", err)
- }
- //及时关闭
- defer file.Close()
- //先读取原来内容,并显示在终端
- reader := bufio.NewReader(file)
- for {
- str, err := reader.ReadString('\n')
- if err == io.EOF { // 如果读取到文件的末尾
- break
- }
- //显示到终端
- fmt.Print(str)
- }
-
- //准备写入5句内容
- content := "你好,北京\r\n"
- writer := bufio.NewWriter(file)
- for i := 0; i < 5; i++ {
- writer.WriteString(content)
- }
-
- //因为Writer是带缓冲的,因此在调用WriterString方法时,其实内容是先写入到缓冲的
- //所以需要调用Flush方法,将缓冲中的数据真正写入到文件中,否则文件中会丢失数据
- writer.Flush()
- }
(1).案例:编写一个程序,将一个文件的内容,写入到另一个文件,注意:这两个文件已经存在了.
说明:使用ioutil.ReadFile,ioutil.WriterFile完成写文件的任务
- package main
-
- import (
- "fmt"
- "io/ioutil"
- )
-
- func main() {
- //将"f:/www/test2.txt" 内容导入 f:/www/test.txt"
- //1.首先将test2.txt内容读取到内存
- //2.将读取到内容写入f:/www/test.txt
- filePath := "f:/www/test2.txt"
- file2Path := "f:/www/test.txt"
- //ReadFile 从filename指定的文件中读取数据并返回文件的内容
- data, err := ioutil.ReadFile(filePath)
- if err != nil {
- fmt.Printf("read file err= %v", err)
- return
- }
- //函数向filename指定的文件中写入数据。如果文件不存在将按给出的权限创建文件,否则在写入数据之前清空文件。
- err = ioutil.WriteFile(file2Path, data, 0666)
- if err != nil {
- fmt.Println("writer file err= %v", err)
- return
- }
- }
(2).判断文件/文件夹是否存在
判断文件或文件夹是否存在的方法为使用os.Stat()函数返回的错误值进行判断:
1).如果返回的错误为 nil ,说明文件或文件夹存在
2).如果返回的错误类型使用 os.IsNotExist()判断为 true ,说明文件或文件夹不存在
3).如果返回的错误为其它类型,则不确定是否在存在
func Stat
- func Stat(name string) (fi FileInfo, err error)
- //Stat返回一个描述name指定的文件对象的FileInfo。如果指定的文件对象是一个符号链接,返回的FileInfo描述该符号链接指向的文件的信息,本函数会尝试跳转该链接。如果出错,返回的错误值为*PathError类型。
func IsNotExist
- func IsNotExist(err error) bool
- //返回一个布尔值说明该错误是否表示一个文件或目录不存在。ErrNotExist和一些系统调用错误会使它返回真
- func PathExists(path string) (bool, error) {
- _, err := os.Stat(path)
- if err == nil { //文件或目录存在
- return true, nil
- }
- if os.IsNotExists(err) {
- return false, nil
- }
- return false, err
- }
案例: 将一张图片/电影/mp3拷贝到另外一个文件e/abc.jpg
io包func Copy():
函数:
func Copy(dst Writer, src Reader) (written int64, err error)
说明:
将src的数据拷贝到dst,直到在src上到达EOF或发生错误。返回拷贝的字节数和遇到的第一个错误。
对成功的调用,返回值err为nil而非EOF,因为Copy定义为从src读取直到EOF,它不会将读取到EOF视为应报告的错误。如果src实现了WriterTo接口,本函数会调用src.WriteTo(dst)进行拷贝;否则如果dst实现了ReaderFrom接口,本函数会调用dst.ReadFrom(src)进行拷贝
注意; copy’函数是 io 包提供的.
- package main
-
- import (
- "fmt"
- "io"
- "os"
- "bufio"
- )
-
- //自己编辑一个函数,接收两个文件路径srcFileName, dstFileName
- func Copy(srcFileName string, dstFileName 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
- }
-
- //通过dstFile,获取Writer
- writer := bufio.NewWriter(dstFile)
- defer dstFile.Close()
-
- return io.Copy(writer, reader)
- }
-
- func main() {
- //将"f:/www/11.png" 拷贝到f:/下"
- srcFile := "f:/www/11.png"
- dstFile := "f:/11.png"
- _, err := Copy(srcFile, dstFile)
- if err == nil {
- fmt.Println("拷贝完成")
- } else {
- fmt.Printf("拷贝错误,err = %v\n", err)
- }
- }
说明:
统计一个文件中含有的英文,数字,空格及其他字符数量
- package main
-
- import (
- "fmt"
- "io"
- "os"
- "bufio"
- )
-
- //定义一个结构体,用于保存统计的结果
- type CharCount struct {
- ChCount int //记录英文个数
- NumCount int //记录数字个数
- SpaceCount int //记录空格个数
- OtherCount int //记录其他字符个数
-
- }
-
- func main() {
- //思路: 打开一个文件,创建一个Reader
- //每读一行,就去统计该行有多少英文,数字,空格和其他字符
- //然后将结果保存到一个结构体中
-
- fileName := "f:/www/test3.txt"
- file, err := os.Open(fileName)
- if err != nil {
- fmt.Printf("open file err = %v\n", err)
- return
- }
-
- defer file.Close()
- //定义一个CharCount实例
- var count CharCount
- //创建一个Reader
- reader := bufio.NewReader(file)
- //循环读取reader里的内容
- for {
- str, err := reader.ReadString('\n')
- if err == io.EOF { //读到文件末尾就退出
- break
- }
- //遍历str,进行统计
- //为了兼容中文字符,可以将str转成[]rune
- str = []rune(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\n",
- count.ChCount, count.NumCount, count.SpaceCount, count.OtherCount)
- }
os.Args是一个string切片,用来存储所有的命令行参数
var Args []string
Args保管了命令行参数,第一个是程序名
- package main
-
- import(
- "fmt"
- "os"
- )
-
- func main() {
- fmt.Println("命令行的参数有:", len(os.Args))
- //遍历os.Args切片,就可以得到所有的命令行输入参数值
- for i, v := range os.Args {
- fmt.Printf("args[%v]=%v\n", i, v)
- }
- }
- PS F:\www\go-data\src\go_code\argsdemo> go build -o test.exe .\main.go
- PS F:\www\go-data\src\go_code\argsdemo> .\test.exe tom d:/www 12
- 命令行的参数有: 4
- args[0]=F:\www\go-data\src\go_code\argsdemo\test.exe
- args[1]=tom
- args[2]=d:/www
- args[3]=12
说明:前面的方式是比较原生的方式,对解析参数不是特别的方便,特别是带有指定参数形式的命令行.
比如:cmd>main.exe -f c:/aaa.txt -p 200 -u root 这样的形式命令行, go 设计者给我们提供了 fiag 包,可以方便的解析命令行参数,而且参数顺序可以随意
- //请编写一段代码,可以获取命令行各个参数
- D:/goproject/src/go_code>test.exe -u root -pwd root -h 192.168.1.1 -port 3306
- user=root
- pwd=root
- host=192.168.1.1
- port=3306
- package main
-
- import (
- "fmt"
- "flag"
- )
-
- func main() {
- //定义几个变量,用于接收命令行参数值
- var user string
- var pwd string
- var host string
- var port int
- //&user: 接收用户输入命令行中输入的 -u 后面的参数
- //"u": 就是-u指定参数
- //"":默认值
- //"用户名,默认为空":参数说明
- flag.StringVar(&user, "u", "", "用户名,默认为空")
- flag.StringVar(&pwd, "pwd", "", "密码,默认为空")
- flag.StringVar(&host, "host", "", "主机,默认为空")
- flag.IntVar(&port, "port", 3306, "端口,默认为空")
- //很重要的参数,转换,必须调用该方法
- flag.Parse()
- //输出结果
- fmt.Printf("user=%v,pwd=%v,host=%v,port=%v", user, pwd, host, port)
- }
- #go build -o test.exe
- #.\test.exe -u zhangs -pwd 123456
- #user=zhangs,pwd=123456,host=,port=3306