文件操作
-
文件读取
使用
os.Open()
打开文件后只能够读,不能够用于写,注意打开文件后返回错误和文件指针,那么判断错误要写在文件关闭的前面,因为有错误的话文件为空,不能执行close。package main import ( "bufio" "fmt" "io" "io/ioutil" "os" ) // 利用read读取文件,可以自定义每次读取的位数 func ReadFromRead() { //open函数里可以是绝对路径,也可以是相对路径(从当前文件夹目录下) fileObj, err := os.Open("./main.go") if err != nil { fmt.Printf("Open file failed,err:%v", err) return } //关闭文件可以用defer来确保最后关闭文件 defer fileObj.Close() //用循环读完文件所有内容 //读文件 read()参数为接受读出来的数据的[]byte,最大读取长度为字节切片的长度,两个返回值一个是实际读取长度和错误 tmp := make([]byte, 128) for { n, err := fileObj.Read(tmp) if err == io.EOF { fmt.Println("读完了") } if err != nil { fmt.Printf("Open file failed,err:%v", err) return } fmt.Printf("读取了%d个字节\n", n) // fmt.Printf("%s", string(tmp[:n])) fmt.Println(string(tmp[:n])) //当读取的字节少于128个字节时,说明没有剩余未读取的字节 if n < 128 { return } } } //利用bufio创建一个reader实现读取,可以实现一行一行的读取 func ReadFromBufio() { //open函数里可以是绝对路径,也可以是相对路径(从当前文件夹目录下) fileObj, err := os.Open("./main.go") if err != nil { fmt.Printf("Open file failed,err:%v", err) return } //关闭文件可以用defer来确保最后关闭文件 defer fileObj.Close() // 创建一个用来从文中读取内容的对象 reader := bufio.NewReader(fileObj) for { line, err := reader.ReadString('\n') //换行符表示每次只读一行,注意是字符 if err == io.EOF { fmt.Println("读完了") return } if err != nil { fmt.Printf("read line failed,err:%v", err) return } //自带换行 fmt.Print(line) } } //可以一次性读取文件的所有内容, //不用先声明一个file类型,自动打开和关闭文件 func ReadFromIoutil() { ret, err := ioutil.ReadFile("./main.go") if err != nil { fmt.Printf("read line failed,err:%v", err) return } //注意返回的是[]byte,打印时转换为字符串再打印 fmt.Println(string(ret)) } func main() { // ReadFromRead() // ReadFromBufio() ReadFromIoutil() }
-
文件写入
os.OpenFile()
能够以指定模式打开文件,从而实现文件写入功能。打开文件模式由os.OpenFile()
的第二个参数flag决定,第三个参数为权限,为一个八进制数,在linux环境下常用,window下不常用,最好乱写一个没有权限。flag各个含义如下:模式 含义 os.O_WRONLY
只写 os.O_CREATE
创建文件(文件不存在会自动创建) os.O_RDONLY
只读 os.O_RDWR
读写 os.O_TRUNC
清空(与追加智能有一个) os.O_APPEND
追加 package main import ( "bufio" "fmt" "io/ioutil" "os" ) //使用Os.OpenFile用相应模式打开的文件才能够写 //使用write写入信息 func writeDemo() { //os.OpenFile的第二个参数本质上是一个数,可以看成是不同的二进制数,不同的位置为1表示不同的含义,所以可以用|来连接表示多种模式并行 fileObj, err := os.OpenFile("./xxx.txt", os.O_WRONLY|os.O_TRUNC|os.O_CREATE, 0644) if err != nil { fmt.Printf("Open file failed,err:%v", err) return } //使用write写信息,参数是[]byte,所以要注意类型转换 fileObj.Write([]byte("Hello,卡卡1\n")) //使用writeString写信息,参数是一个string fileObj.WriteString("Hello,zq") defer fileObj.Close() } // 使用Bufio缓存写入 func writeDemo2() { //os.OpenFile的第二个参数本质上是一个数,可以看成是不同的二进制数,不同的位置为1表示不同的含义,所以可以用|来连接表示多种模式并行 fileObj, err := os.OpenFile("./xxx.txt", os.O_WRONLY|os.O_TRUNC|os.O_CREATE, 0644) if err != nil { fmt.Printf("Open file failed,err:%v", err) return } defer fileObj.Close() //创建一个写的对象 wr := bufio.NewWriter(fileObj) //将数据先写入缓存 wr.WriteString("Hello,卡卡2") //将缓存的内容写进文件 wr.Flush() } //使用ioutil写入文件,注意是字符切片,要类型转换 func writeDemo3() { str := "Hello,卡卡3" err := ioutil.WriteFile("./xxx.txt", []byte(str), 0666) if err != nil { fmt.Println("write file failed,err", err) return } } func main() { // writeDemo() // writeDemo2() writeDemo3() }
-
使用bufio读取标准输入
package main import ( "bufio" "fmt" "os" ) // scan默认空格为换行符,所以不能直接输入含有空格的内容 func useScan() { var s string fmt.Print("请输入内容:") fmt.Scanln(&s) fmt.Printf("你输入的内容是%s\n", s) } //利用bufio可以往标准输入或输出中写,即实现从终端中读取输入或者打印数据至终端上 func useBufio() { var s string //os.Stdin表示为标准输入,即从终端中读取 //newReader的参数是接口类型 reader := bufio.NewReader(os.Stdin) fmt.Print("请输入内容:") //表示以换行符结束 s, _ = reader.ReadString('\n') fmt.Printf("你输入的内容是%s\n", s) } func main() { useScan() useBufio() }
-
实现copyfile
package main import ( "fmt" "io" "os" ) func copyFile(dstName, srcName string) (written int64, err error) { src, err := os.Open(srcName) if err != nil { fmt.Printf("open %s failed,err:%v.\n", srcName, err) return } defer src.Close() dst, err := os.OpenFile(dstName, os.O_CREATE|os.O_WRONLY, 0644) if err != nil { fmt.Printf("open %s failed,err:%v.\n", dstName, err) return } defer dst.Close() return io.Copy(dst, src) } func main() { _, err := copyFile("dst.txt", "src.txt") if err != nil { fmt.Printf("copy fail:%v ", err) return } fmt.Println("copy succeed") }
-
中间插入文件内容
使用
seek
可以移动光标,但是移动的是位数,换行符占2位,不方便,通过建立临时存储区存储前半部分内容,插入内容后再加上后续内容是通用方法,这种方法使用read
读取的是字符数,换行符只占1个字符package main import ( "fmt" "io" "os" ) //利用seek函数可以选择起始操作位置,其中第一个参数表示相对偏移量,第二个参数表示相对位置,0为开头,1为当前位置,2为末尾 //注意移动到这个位置后直接执行写操作会覆盖原来的值,因此需要新建临时文件保存值 func insert() { fileobj, err := os.OpenFile("./xxx.txt", os.O_RDWR, 0644) if err != nil { fmt.Printf("open file failed,err:%v", err) return } //创建临时文件存储前面内容,再插入内容,然后读入后面的内容,从而实现向中间插入内容 tmp, err := os.OpenFile("./tmp.txt", os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0644) if err != nil { fmt.Printf("creat tempFile failed, err:%v", err) return } //建立缓冲区,读取前部分内容,注意换行符占一个字节 buf := make([]byte, 2) n, err := fileobj.Read(buf) if err != nil { fmt.Printf("read file failed err:%v", err) return } //将缓冲区内容写入临时文件 tmp.Write(buf[:n]) //写入插入内容 tmp.Write([]byte("b\n")) //写入原文件的后续内容 last := make([]byte, 1024) for { n, err := fileobj.Read(last) if err == io.EOF { break } else if err != nil { fmt.Printf("read file failed err:%v", err) return } tmp.Write(last[:n]) } fileobj.Close() tmp.Close() //通过重命名为同样名字将原来的文件覆盖 os.Rename("./tmp.txt", "./xxx.txt") } func main() { insert() }