Go语言操作文件
文件的打开与关闭
- 文件的打开
- 在Go语言的os包中提供了一个函数, 叫做Open, 就是专门用于打开某一个文件的
-
注意点
:
如果文件不存在不会自动创建,通过open函数打开的文件只能读取, 不能写入
- 文件的关闭
- 在Go语言的os包中提供了一个函数, 叫做Close, 就是专门用于关闭某个打开文件的
package main
import (
"fmt"
"os"
)
func main() {
/*
1.如何打开文件?
在Go语言的os包中提供了一个函数, 叫做Open, 就是专门用于打开某一个文件的
注意点:
如果文件不存在不会自动创建
通过open函数打开的文件只能读取, 不能写入
2.如何关闭文件?
在Go语言的os包中提供了一个函数, 叫做Close, 就是专门用于关闭某个打开文件的
*/
//打开文件
//func Open(name string) (*File, error)
fp, err := os.Open("D:/wjh.txt")
if err != nil {
fmt.Println("打开文件失败")
}else {
fmt.Println(fp)
}
//关闭文件
defer func() {
if err = fp.Close(); err != nil {
fmt.Println("文件关闭失败")
}else {
fmt.Println("文件关闭成功")
}
}()
}
文件的读取操作
- 通过os包中的Read函数读取
-
注意点:
Read函数会将读取到的数据放到指定的切片中, 并且会一次性将所有的数据都读取进来会将读取到的byte个数返回给我们, 并且还会返回一个error,
如果读取成功, 那么error等于nil, 如果读取失败那么error就不等于nil
package main
import (
"fmt"
"os"
)
func main() {
/*
第一种读取的方式:
通过os包中的Read函数读取
func (f *File) Read(b []byte) (n int, err error)
Read函数会将读取到的数据放到指定的切片中, 并且会一次性将所有的数据都读取进来
会将读取到的byte个数返回给我们, 并且还会返回一个error,
如果读取成功, 那么error等于nil, 如果读取失败那么error就不等于nil
*/
//打开一个文件
fp, err := os.Open("D:/wjh.txt")
if err != nil {
fmt.Println("打开文件失败")
} else {
fmt.Println("打开文件成功")
}
//关闭文件
defer func() {
if err = fp.Close();err != nil {
fmt.Println("关闭文件失败")
}
}()
//读取文件内容
// read函数接收一个切片, 会将读取到的数据放到指定的切片中
// 注意点: 会一次性将文件中的数据全部读取进来
//定义一个切片保存读取的数据
sce := make([]byte,7)
for {
len, err := fp.Read(sce)
if err != nil || len <= 0 {
break
}
fmt.Print(string(sce[: len]))
}
}
- 带缓冲区读取数据
-
注意点:
当文件较大时,为了提高效率建议使用带缓冲区方式读取
package main
import (
"bufio"
"fmt"
"io"
"os"
)
func main() {
/*
第一种读取的方式:
通过bufio包中的ReadBytes和ReadString函数
func (b *Reader) ReadBytes(delim byte) (line []byte, err error)
*/
//打开文件
fp, err := os.Open("D:/wjh.txt")
if err != nil {
fmt.Println("打开文件失败")
}
//关闭文件
defer func() {
if err = fp.Close(); err != nil {
fmt.Println("关闭文件失败")
}
}()
//创建缓冲区
// 将打开的文件句柄传递给NewReader函数, 会返回一个新的句柄
// 缓冲区默认的大小是4096
r := bufio.NewReader(fp)
// 利用缓冲区的句柄来读取数据
// 接收一个参数, 这个参数用于告诉ReadBytes函数, 读取到什么地方接收
// 会将读取到的数据放到一个切片中返回给我们
/*
注意点:
abcdefg\n
1234567
第一次读取: buf = abcdefg\n
第二次读取: buf = 1234567
但是由于第二次读取一直读到了文件的末尾都没有读到\n, 所以ReadBytes函数就给err赋值了一个io.EOF
所以如果1234567后面没有\n, 并且是先判断错误, 那么就会少输出一次
*/
/*for {
buff, err := r.ReadBytes('\n')
fmt.Print(string(buff))
if err == io.EOF {
break
}
}*/
for {
str, err := r.ReadString('\n')
fmt.Print(str)
if err == io.EOF {
break
}
}
}
- 通过ioutil包中的ReadFile函数读取
- func ReadFile(filename string) ([]byte, error)
package main
import (
"fmt"
"io/ioutil"
)
func main() {
/*
第三种读取的方式:
通过ioutil包中的ReadFile函数读取
func ReadFile(filename string) ([]byte, error)
*/
// 会将指定路径中的文件一次性读取进来
// 接收一个参数: 用于传递需要读取的文件路径
// 返回两个值:
// 第一个返回值: 读取到的数据
// 第二个返回值: 读取失败就不等于nil
buff, err := ioutil.ReadFile("D:/wjh.txt")
if err != nil {
fmt.Println("读取文件失败")
} else {
fmt.Println(string(buff))
}
}
文件写入操作
- 通过os包中的Write函数一次性写入
- 注意点: Open函数打开的文件只能读取, 不能写入
Create函数的作用: 创建一个文件
文件不存在, 会自动创建一个新的
文件存在, 会覆盖以前的(相当于创建了一个新的替换掉了以前的旧的)
package main
import (
"fmt"
"os"
)
func main() {
/*
第一种写入的方式:
通过os包中的Write函数写入
*/
//1.打开一个文件
// 注意点: Open函数打开的文件只能读取, 不能写入
// Create函数的作用: 创建一个文件
// 注意点: 文件不存在, 会自动创建一个新的
// 文件存在, 会覆盖以前的(相当于创建了一个新的替换掉了以前的旧的)
//func Create(name string) (file *File, err error)
fp, err := os.Create("D:/lnj.txt")
if err != nil {
fmt.Println("打开文件失败")
}
//2.关闭文件
defer func() {
if err = fp.Close();err != nil {
fmt.Println("关闭文件失败")
}
}()
//3.写入文件内容
//func (f *File) Write(b []byte) (n int, err error)
// 特点: 会将指定的数据一次性写入到文件中
// 所以不适合数据量比较大的情况
buf := []byte{'w','j','h','\r','\n'}
len, err := fp.Write(buf)
if err != nil {
fmt.Println("写入失败")
}else {
fmt.Print("写入了", len,"字节")
}
}
- 通过bufio包中的Write和WirteString函数写入(带缓冲区的方式)
package main
import (
"bufio"
"fmt"
"os"
)
func main() {
/*
第二种写入的方式:
通过bufio包中的Write和WirteString函数写入
*/
//创建一个文件
fp, err := os.Create("D:/lnj.txt")
if err != nil {
fmt.Println("创建文件失败")
}
//关闭文件
defer func() {
if err = fp.Close(); err != nil {
fmt.Println("关闭文件失败")
}
}()
//1.创建一个写入缓冲区
//func NewWriter(w io.Writer) *Writer
w := bufio.NewWriter(fp)
//2.写入数据
/*//func (b *Writer) Write(p []byte) (nn int, err error)
//写入的内容
sce := []byte{'w','j','h','\r','\n'}
len, err := w.Write(sce)
if err != nil {
fmt.Println("写入文件失败")
}else {
fmt.Println("写入了",len,"字节的数据")
}
*/
//使用WriteString函数写入内容
//func (b *Writer) WriteString(s string) (int, error)
len, err := w.WriteString("www.it666.com\r\n")
if err != nil {
fmt.Println("写入数据失败")
}else {
fmt.Println("写入了",len,"字节")
}
//注意点:
// 如果通过带缓冲区的方式写入数据, 那么必须在写入完毕之后刷新一下缓冲区, 才会将缓冲区中的数据真正的写入到文件中
w.Flush()
}
- 通过ioutil包中WirteFile函数写入
- func WriteFile(filename string, data []byte, perm os.FileMode) error
package main
import (
"fmt"
"io/ioutil"
)
func main() {
/*
第三种写入的方式:
通过ioutil包中WirteFile函数写入
func WriteFile(filename string, data []byte, perm os.FileMode) error
*/
buf := []byte{'w','j','h','\r','\n'}
err := ioutil.WriteFile("D:/wjh.txt", buf, 0666)
if err != nil {
fmt.Println("写入数据失败")
}else {
fmt.Println("写入数据成功")
}
}
文件追加数据操作
package main
import (
"bufio"
"fmt"
"io"
"os"
)
func main() {
/*
os包中的Open函数只能读取不能写入
os包中的Create函数可以读取也可以写入, 但是每次执行都会覆盖原有的文件, 每次执行都是一个空文件
所以: 如果想要往文件中追加数据, 利用如上两个方法是不行的
所以: 需要通过os包中的另一个函数: OpenFile
作用: 打开一个文件, 并且文件不存在可以创建(注意是可以不是自动)
第一个参数: 需要打开文件的路径
第二个参数: 以什么模式打开文件 (只读/只写/可读可写/追加/)
模式可以同时指定多个, 多个之间使用|分隔, 例如 O_CREATE | O_WRONLY
第三个参数: 指定文件的权限, 只对Linux系统有效, 在Windows下无效
func OpenFile(name string, flag int, perm FileMode) (file *File, err error)
const (
O_RDONLY int = syscall.O_RDONLY // 只读模式打开文件
O_WRONLY int = syscall.O_WRONLY // 只写模式打开文件
O_RDWR int = syscall.O_RDWR // 读写模式打开文件
O_APPEND int = syscall.O_APPEND // 写操作时将数据附加到文件尾部
O_CREATE int = syscall.O_CREAT // 如果不存在将创建一个新文件
O_EXCL int = syscall.O_EXCL // 和O_CREATE配合使用,文件必须不存在
O_SYNC int = syscall.O_SYNC // 打开文件用于同步I/O
O_TRUNC int = syscall.O_TRUNC // 如果可能,打开时清空文件
)
0.没有任何权限
1.执行权限(如果是可执行程序, 可以运行)
2.写权限
3.写权限和执行权限
4.读权限
5.读权限和执行权限
6.读权限和写权限
7.读权限和写权限以及执行权限
一般情况下写 0666
注意点: OpenFile和Open函数一样, 打开文件之后需要手动关闭文件
*/
//1.打开一个文件
fp, err := os.OpenFile("D:/lnj.txt", os.O_CREATE|os.O_RDWR |os.O_APPEND, 0666)
if err != nil {
fmt.Println("创建文件失败")
}
//关闭文件
defer func() {
if err = fp.Close(); err != nil {
fmt.Println("关闭文件失败")
}
}()
//一次性写入数据到文件
len, err := fp.WriteString("www.it666.com\r\n")
if err != nil {
fmt.Println("写入数据失败")
}else {
fmt.Println("写入了",len,"字节的数据")
}
//一次性读取所有数据
//注意点: 不能读写一起操作,否则会读取数据失败
//创建切片保存读取数据
buf := make([]byte, 1024)
//读取文件中的数据
length, err := fp.Read(buf)
if err != nil {
fmt.Println("读取文件失败")
}else {
fmt.Println(string(buf[: length]))
}
//使用缓冲区写入追加数据
//创建写入缓冲区
w := bufio.NewWriter(fp)
//写入数据
len, err := w.WriteString("我是小老虎\r\n")
if err != nil {
fmt.Println("写入数据失败")
}else {
fmt.Println("写入了",len,"字节的数据")
}
//刷新缓冲区数据
w.Flush()
//使用缓冲区读取数据
//创建读取的缓冲区
r := bufio.NewReader(fp)
//读取数据
for{
str, err := r.ReadString('\n')
fmt.Print(str)
if err == io.EOF {
break
}
}
}
获取文件信息
- os包中Stat函数用来获取文件的信息
- func Stat(name string) (fi FileInfo, err error)
package main
import (
"fmt"
"os"
)
func main() {
info,err := os.Stat("D:/lnj.txt")
if err != nil {
fmt.Println(err)
}else {
fmt.Println(info.Name()) //文件名称
fmt.Println(info.Size()) //文件大小
fmt.Println(info.ModTime()) //文件修改时间
fmt.Println(info.IsDir()) //是否为目录
}
}
利用缓冲区方式拷贝文件
package main
import (
"bufio"
"fmt"
"io"
"os"
)
func main() {
//拷贝一张照片
//文件较大,使用带缓冲区方式拷贝文件
//读取文件
//1.打开文件
rp, err := os.Open("D:/20150705_IMG_0024.JPG")
if err != nil {
fmt.Println("打开文件失败")
}
//2.关闭文件
defer func() {
if err = rp.Close(); err != nil{
fmt.Println("关闭文件失败")
}
}()
//写入文件
//1.创建文件
wp, err := os.Create("D:/hui.jpg")
if err != nil {
fmt.Println("创建文件失败")
}
//2.关闭文件
defer func() {
if err = wp.Close(); err != nil {
fmt.Println("关闭文件失败")
}
}()
//创建读取缓冲区
r := bufio.NewReader(rp)
//创建写入缓冲区
w := bufio.NewWriter(wp)
//利用io包中的copy函数进行文件拷贝
//func CopyN(dst Writer, src Reader, n int64) (written int64, err error)
len, err := io.Copy(w,r)
if err != nil {
fmt.Println("拷贝文件失败")
}else {
fmt.Println("拷贝了",len,"字节的数据")
}
}
遍历目录操作
package main
import (
"fmt"
"io/ioutil"
)
func main() {
//遍历文件夹中的文件,将遍历到的所有文件的路径保存到切片中
//func ReadDir(dirname string) ([]os.FileInfo, error)
sce := listDir("D:/demo")
fmt.Println(sce)
}
func listDir(path string) (sce []string) {
//1.读取指定的目录
dir, err := ioutil.ReadDir(path)
if err != nil {
fmt.Println("读取目录失败")
} else {
//2.遍历文件信息
for _, value := range dir {
//3.判断是否为目录
if value.IsDir() {
//再次遍历子目录
sce1 := listDir(path + "/" + value.Name())
for _, v := range sce1 {
sce = append(sce, v)
}
//是文件存储在切片中
}else {
sce = append(sce, path + "/" + value.Name())
}
}
}
return
}