9.2 Go 文件IO操作
9.2 Go 文件IO操作
1.1.1. bufio包
带有缓冲区的IO读写操作,用于读写文件,以及读取键盘输入
func main() { //NewReader返回一个结构体对象指针 reader := bufio.NewReader(os.Stdin) //ReaderLine返回字节切片 data, _, _ := reader.ReadLine() fmt.Printf("data类型:%T\n 数值:%v\n", data, data) //用string()内置函数强转切片为stirng str := string(data) fmt.Printf("data类型:%T\n 数值:%v\n", str, str) }
案例结果
yugoMBP:day01 yuchao$ go run demo01_variable.go 妖怪,放开我爷爷 data类型:[]uint8 数值:[229 166 150 230 148 190 229 188 128 230 136 145 231 136 183 231 136 183] data类型:string 数值:妖放开我爷爷
1.1.2. 文件读写
文件主要用于保存数据,比如图片、视频、音乐,文档等。
程序的输入和输出流。
流: 指数据源(文件)和程序(内存)之间传输的路径 输入流: 数据从文件到内存的路径 输出流: 数据从内存到文件的路径
1.2. os.File
os.File封装了所有文件相关操作。
//File是一个结构体 type File struct{ //内涵隐藏或非导出字段 }
1.3. 打开/关闭文件
使用函数和方法
//打开文件,返回文件句柄指针 func Open(name string)(file *File,err error) func (*File)Close()error //Close关闭文件f,文件此时无法读写。
打开,关闭文件,示例
package main import ( "fmt" "os" ) func main() { //打开文件,获取文件句柄 file, err := os.Open("/Users/yuchao/go/src/gostudy/gobook/mygolang.txt") if err != nil { fmt.Println("打开文件出错了:", err) } //file文件句柄就是一个 指针类型 fmt.Printf("文件句柄类型:%T 值:%v\n ", file, file) //打开文件,注意要释放,关闭文件资源 err = file.Close() if err != nil { fmt.Println("出错了", err) } }
只读取文本
package main import ( "bufio" "fmt" "io" "os" ) func main() { //只读的方式打开文本 file, err := os.Open("filepath") if err != nil { fmt.Println("open file failed, err:", err) return } defer file.Close() reader := bufio.NewReader(file) for { line, err := reader.ReadString('\n') if err == io.EOF { break } if err != nil { fmt.Println("read file failed, err:", err) return } fmt.Println(line) } }
1.4. 写入文件os.OpenFile
Go标准包中os.OpenFile用于打开文件的函数,可以指定参数,文件权限,文件名等。
操作成功返回文件句柄。
func OpenFile(name string, flag int, perm FileMode) (*File, error)
//参数解析
name string 文件名,路径
flag int 文件打开模式
perm FileMode unix文件权限
文件打开模式参数注解( OpenFile函数的参数中的源码)
打开标记: O_RDONLY:只读模式(read-only) O_WRONLY:只写模式(write-only) O_RDWR:读写模式(read-write) O_APPEND:追加模式(append) O_CREATE:文件不存在就创建(create a new file if none exists.) O_EXCL:与 O_CREATE 一起用,构成一个新建文件的功能,它要求文件必须不存在(used with O_CREATE, file must not exist) O_SYNC:同步方式打开,即不使用缓存,直接写入硬盘 O_TRUNC:打开并清空文件 文件权限(unix权限位):只有在创建文件时才需要,不需要创建文件可以设置为 0。os库虽然提供常量,一般直接写数字,如0664。 如果你需要设置多个打开标记和unix权限位,需要使用位操作符"|"
解析bufio
bufio包实现了有缓冲的I/O。它包装一个io.Reader或io.Writer接口对象,创建另一个也实现了该接口,且同时还提供了缓冲和一些文本I/O的帮助函数的对象。
创建文件实例
package main import ( "bufio" "fmt" "os" ) func main() { filePath := "/Users/yuchao/hello.txt" //O_WRONLY:只写模式(write-only) //O_CREATE:文件不存在就创建 file, err := os.OpenFile(filePath, os.O_WRONLY|os.O_CREATE, 0666) if err != nil { fmt.Printf("打开文件出错了:%v\n", err) return } defer file.Close() //及时关闭文件句柄,防止内存泄露 str := "你好,我是够浪\n" //定义字符串 //写入数据 writer := bufio.NewWriter(file) for i := 0; i < 10; i++ { writer.WriteString(str) } writer.Flush() //将缓冲区的数据,写入到磁盘文件中 }
覆盖写入文件内容
package main import ( "bufio" "fmt" "os" ) func main() { //打开文件,覆盖原有数据 //写入新数据,每天多努力一点,你会发现你更适合加班 filePath := "/Users/yuchao/hello.txt" //O_WRONLY:只写模式(write-only) //O_TRUNC:打开并清空文件 file, err := os.OpenFile(filePath, os.O_WRONLY|os.O_TRUNC, 0666) if err != nil { fmt.Printf("打开文件失败:%v\n", err) return } //关闭文件句柄 defer file.Close() //写入新数据 str := "每天多努力一点,你会发现你更适合加班\n" //写入携带缓存的 *Writer writer := bufio.NewWriter(file) //循环写入5条数据 for i := 0; i < 5; i++ { writer.WriteString(str) } /* writer是携带缓存的,因此调用writerString方法, 其实内容是先写入到缓存中,必须调用flush,将缓冲的数据写入到文件中 */ writer.Flush() }
打开已存在的文件,追加
写入内容
package main import ( "bufio" "fmt" "os" ) func main() { filePath := "/Users/yuchao/hello.txt" //O_WRONLY:只写模式(write-only) //O_APPEND:追加模式(append) file, err := os.OpenFile(filePath, os.O_WRONLY|os.O_APPEND, 0666) if err != nil { fmt.Printf("打开文件失败:%v\n", err) return } //关闭文件句柄 defer file.Close() //写入新数据 str := "真的吗?那我一定要好好加班\n" //写入携带缓存的 *Writer writer := bufio.NewWriter(file) //循环写入5条数据 for i := 0; i < 5; i++ { writer.WriteString(str) } /* writer是携带缓存的,因此调用writerString方法, 其实内容是先写入到缓存中,必须调用flush,将缓冲的数据写入到文件中 */ writer.Flush() }
打开一个已有文件,读取
出原本的内容显示在终端,并且追加
5句"加班万岁"
。
package main import ( "bufio" "fmt" "io" "os" ) func main() { //打开一个已有文件,`读取`出原本的内容显示在终端,并且`追加`5句`"加班万岁"`。 filePath := "/Users/yuchao/hello.txt" //O_WRONLY:只写模式(write-only) //O_APPEND:追加模式(append) //OpenFile返回一个文件指针 file, err := os.OpenFile(filePath, os.O_RDWR|os.O_APPEND, 0666) if err != nil { fmt.Printf("打开文件失败:%v\n", err) return } //关闭文件句柄 defer file.Close() //读取原有内容,打印输出 reader := bufio.NewReader(file) for { str, err := reader.ReadString('\n') //如果读取到结尾,结束循环 if err == io.EOF { break } if err != nil { fmt.Println("读取文件出错了:", err) } //显示读取到的文本 fmt.Print(str) } //准备写入新内容 newStr := "加班万岁\n" //使用带缓存的*Writer writer := bufio.NewWriter(file) writer.WriteString(newStr) writer.Flush() }
1.5. 文件拷贝
package main import ( "fmt" "io" "os" ) //拷贝文件 dst目的文件 src源文件 func CopyFile(dstFile string, srcFile string) (written int64, err error) { src, err := os.Open(srcFile) if err != nil { fmt.Println("打开文件出错", err) } defer src.Close() dst, err := os.OpenFile(dstFile, os.O_WRONLY|os.O_CREATE, 0644) if err != nil { fmt.Printf("打开文件%s出错,错误:%v\n", dstFile, err) return } defer dst.Close() return io.Copy(dst, src) } func main() { // _, err := CopyFile("/Users/yuchao/helloCopy.txt", "/Users/yuchao/hello.txt") if err == nil { fmt.Println("拷贝完成") } else { fmt.Println("拷贝出错了,错误:", err) } }
1.6. 获取命令行参数
如linux命令
ls -la
os.args包是一个string的切片,用于存储所有命令行参数。
package main import ( "fmt" "os" ) func main() { fmt.Printf("命令行参数有%d个\n", len(os.Args)) for i, v := range os.Args { fmt.Printf("参数%d 是 %v\n", i, v) } }
对代码编译后,进行传参运行
go build main.go
./main alex peiqi xiaofeng //传入三个参数
1.7. flag包解析命令行参数
package main import ( "flag" "fmt" ) func main() { /* flag包可以解析如下命令 ./main -u root -p 123 -h 127.0.0.1 -port 3306 */ //定义用于接收命令行的参数值 var user string var pwd string var host string var port int flag.StringVar(&user, "u", "", "用户名,默认为空") flag.StringVar(&pwd, "p", "", "密码默认为空") flag.StringVar(&host, "h", "localhost", "主机名,默认localhost") flag.IntVar(&port, "port", 3306, "端口号,默认3306") flag.Parse() fmt.Printf("user=%v pwd=%v host=%v port=%v\n", user, pwd, host, port) }
运行flag包解析
yugoMBP:gobook yuchao$ go run main.go -u root -p 123 -h 127.0.0.1 -port 3306 user=root pwd=123 host=127.0.0.1 port=3306