[go学习笔记.第十二章.文件操作] 1.文件的基本介绍以及基本操作

 一.文件的基本介绍

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

输入流和输出流

文件在程序中是以流的形式来操作的

:数据在数据源(文件)和程序(内存)之间经历的路径

输入流: 数据从数据源(文件)到程序 ( 内存)的路径

输出流: 数据从程序(内存)到数据源(文件)的路径

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

 二.文件的基本操作

1.打开文件和关闭文件

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
    }
}

2.读取文件操作

(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函数内部   
}

 3.写文件操作

os.OpenFile函数介绍

第二个参数 flag:文件打开模式(可以组合)参数如下:

 第三个参数 perm:权限控制参数如下:

r:读 ===> 4

w:写 ===> 2

x: 执行 ===> 1

方式一

(1).创建一个新文件,写入内容: 5句 "hello world"

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()
}

(2).打开一个存在的文件,将原来的内容覆盖成新的内容,10句 "hello,你好" 

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()
}

(3).打开一个文件,在原来的内容追加内容, 5句 "你好,world"

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
}

 (3).拷贝文件

案例: 将一张图片/电影/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)
    }
}

 (4).统计英文,数字,空格和其他字符数量

说明:

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

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

flag包用来解析命令行参数

说明:前面的方式是比较原生的方式,对解析参数不是特别的方便,特别是带有指定参数形式的命令行.

比如: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

 [上一节][go学习笔记.第十一章.项目案例] 2.客户信息管理系统

 [下一节] [go学习笔记.第十二章.文件操作] 2.json基本介绍

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
《Go语言学习笔记.pdf》是一本关于Go语言学习学习笔记,内容丰富且简洁明了。本书从基础知识开始,逐步了Go语言的语法、特性和常用库函数等。在学习笔记中,作者通过实际的示例和练习帮助读者理解Go语言的概念和用法。 第一章了Go语言的起源和发展,为读者提供了对Go语言背景的整体了解。第二章讲解了Go语言的基本语法,例如变量声明、循环和条件语句等。通过大量的代码示例,读者能够更好地理解Go语言的语法和结构。 接下来的章节重点了Go语言的并发编程和高级特性。第三章详细了Go语言中的goroutine和channel,这是Go语言并发编程的核心机制。作者通过生动的示例代码和实际应用案例,向读者展示了如何使用goroutine和channel实现并发编程。 第四章和第五章分别了Go语言中的面向对象编程和函数式编程。通过深入讲解Go语言中的结构体、接口和函数,读者能够更好地应用这些特性进行代码设计和开发。 最后几章则了Go语言中常用的库函数和工具。例如,第六章了Go语言中用于网络编程的net包和http包。读者可以学习到如何使用这些库函数构建基于网络的应用程序。 总的来说,《Go语言学习笔记.pdf》是一本非常实用的Go语言学习资料。通过阅读这本书,读者能够系统地学习和理解Go语言的基本概念和高级特性,为之后的Go语言开发打下坚实的基础。无论是初学者还是有一定编程经验的开发者,都能从中获得丰富的知识和经验。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值