Go语言文件操作
文件的打开和关闭
- os包中提供了方法叫做Open,就是专门用于打开某一个文件的
- 注意点:
- 如果文件不存在不会自动创建
- 通过open函数打开的文件只能读取, 不能写入
// 1.打开文件
//os.Open("D:\\lnj.txt")
fp, err := os.Open("D:/lnj.txt") // 推荐写法
if err != nil {
fmt.Println("打开失败")
}else{
fmt.Println(fp)//fp是文件句柄
}
- os包中提供了函数叫做Close,用于关闭某个文件
- 通过defer和匿名函数来关闭文件
// 2.关闭文件
defer func() {
if err = fp.Close(); err !=nil{
fmt.Println("关闭文件失败")
}
}()
文件的读取
- 第一种:通过os包中的Read函数读取(读取较小的文件)
- func (f *File) Read(b []byte) (n int, err error)
- 注意点:
-
这是File的一个方法,由文件来调用
-
接收一个字符型切片,会把读取到的数据保存在切片中(会一次性把文件里所有的东西都读取过来)
-
返回值返回读取到的长度和err(读取到时err为nil)
-
fp, err := os.Open("D:/lnj.txt")
if err != nil{
fmt.Println("打开文件失败")
return
}
// 2.关闭文件
defer func() {
if err = fp.Close(); err != nil{
fmt.Println("关闭文件失败")
}
}()
// sce := make([]byte,7)
//len,err := fp.Read(sce)
// if err != nil{
// fmt.Println("读取失败")
//}else{
// fmt.Println("len = ",len)
// fmt.Println(string(sce[:len]))
//}
//sce := make([]byte,7)
//len,err := fp.Read(sce)
//for ;len>0;{
// fmt.Print(string(buff[:len]))
// // 再次利用Read函数去读取7个字节
// len, err = fp.Read(buff)
//}
sce := make([]byte,7)
for{
len,err := fp.Read(sce)
if err == io.EOF || len < 0{
break
}
// 将读到的数据转换为字符串打印
fmt.Print(string(buff[:len]))
}
- 第二种方式: 通过bufio包中的ReadBytes和ReadString函数(读取较大的文件,如音视频文件)
- func (b *Reader) ReadBytes(delim byte) (line []byte, err error)
- 接收一个参数, 这个参数用于告诉ReadBytes函数, 读取到什么地方接收
- 返回一个切片,用于保存读取到的数据
- ReadString底层也是用ReadBytes实现,只不过转换为了字符串返回
- 步骤
-
创建缓冲区(这样可以不用反复从硬盘里读取,可以增加效率)
-
将打开的文件句柄传递给NewReader函数, 会返回一个新的句柄
-
缓冲区默认的大小是4096
-
// 1.打开文件
fp, err := os.Open("D:/lnj.txt")
if err != nil{
fmt.Println("打开文件失败")
return
}
// 2.关闭文件
defer func() {
if err = fp.Close(); err != nil{
fmt.Println("关闭文件失败")
}
}()
r := bufio.NewReader(fp) //接收一个句柄,返回一个句柄,利用返回的句柄来读取数据
/*
buff, err := r.ReadBytes('\n')
if(err != nil){
fmt.Println("读取失败")
}else{
fmt.Println(string(buff))
}
*/
//str,err := r.ReadString('\n')
for{
buff, err := r.ReadBytes('\n')
fmt.Print(string(buff))
if err == io.EOF{
//if err != nil{
//fmt.Print("读取失败")
//fmt.Print(err)
break
}
}
- 错误读取
/*
abcdefg\n
1234567
第一次读取: buf = abcdefg\n
第二次读取: buf = 1234567
但是由于第二次读取一直读到了文件的末尾都没有读到\n, 所以ReadBytes函数就给err赋值了一个io.EOF
所以如果1234567后面没有\n, 并且是先判断错误, 那么就会少输出一次
*/
/*
for{
buff, err := r.ReadBytes('\n')
if err == io.EOF{
//if err != nil{
//fmt.Print("读取失败")
//fmt.Print(err)
break
}
fmt.Print(string(buff))
}
*/
- 第三种方式
- 通过ioutil包中的ReadFile函数读取(读取较小的文件)
- func ReadFile(filename string) ([]byte, error)
- 接收文件所在地址的字符串,返回读取到的数据和错误
buff,err := ioutil.Readfile("D:/lnj.txt")
if err != nil {
fmt.Println(err)
}else{
fmt.Print(string(buff))
}
文件写入
- 第一种方式
- 通过os包中的Write函数写入(特点:一次性写入,不适合写数据量比较大的文件)
- 注意点:由于通过Open函数打开的文件是只读的不能写入,所以我们需要用Create函数
- Create函数注意点:
- 文件不存在时,自动创建,文件存在时覆盖
- 函数返回文件的句柄和错误信息
- Create函数注意点:
fp,err := os.Create("D:/lnj.txt")
if err != nil {
fmt.Println(err)
return
}
defer func(){
if err = fp.Close();err != nil{
fmt.Println("关闭文件失败")
}
}
//写入数据
buf := []byte{'x','x','z','\r','\n'}
len,err := os.Write(buf)
if err !=nil{
fmt.Println("写入失败")
}else{
fmt.Println("写入成功, 写入了", len, "个字节")
}
- 第二种方式
- 通过bufio包中的Write和WirteString函数写入
- 注意点:
- Write函数接收一个切片,WriteString函数接收要写入的字符串,返回写入数据的长度和错误信息
- 尤其注意:这两个函数是在缓冲区中写入,如果需要真正的写入到文件里面,需要刷新缓冲区,刷新缓冲区用 (缓冲区句柄).Flush()
// 1.创建一个文件
fp, err := os.Create("D:/lnj.txt")
if err != nil{
fmt.Println("打开文件失败")
return
}
// 2.关闭文件
defer func() {
if err = fp.Close(); err !=nil{
fmt.Println("关闭文件失败")
}
}()
// 3.创建一个写入缓冲区
w := bufio.NewWriter(fp)
//buf := []byte{'l','n','j','\r','\n'}
//len, err := w.Write(buf)
len, err := w.WriteString("www.it666.com\r\n")
if err != nil {
fmt.Println("打开文件失败")
}else{
fmt.Println("写入了",len,"个字符")
}
//刷新缓冲区
w.Flush()
- 第三种方式
- 通过ioutil包中的Write和WirteString函数写入
- func WriteFile(filename string, data []byte, perm os.FileMode) error
- 第一个参数: 文件地址的自字符串
- 第二个参数: 写入的内容的切片
- 第三个参数: 指定文件的权限, 只对Linux系统有效, 在Windows下无效
- 返回值:返回err
buf := []byte{'l','n','j','\r','\n'}
err := ioutil.WriteFile("D:/lnj.txt", buf, 0666)
if err != nil{
fmt.Println("写入数据失败")
}else{
fmt.Println("写入数据成功")
}
文件读写
-
以上的代码只能读或者写入的时候会覆盖原文件,如果要对文件内容进行追加,我们需要用到文件的读写操作
-
os包中有一个函数叫OpenFile 作用:打开一个文件, 并且文件不存在可以创建(注意是可以不是自动)
-
func OpenFile(name string, flag int, perm FileMode) (*File, error)
-
第一个参数: 需要打开文件的路径
-
第二个参数: 以什么模式打开文件 (只读/只写/可读可写/追加/)模式可以同时指定多个, 多个之间使用|分隔, 例如 O_CREATE | O_WRONLY
-
第三个参数: 指定文件的权限, 只对Linux系统有效, 在Windows下无效
-
模式的种类: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函数一样, 打开文件之后需要手动关闭文件
以下代码为文件内容的追加:
fp, err := os.OpenFile("D:/lnj.txt", os.O_APPEND | os.O_RDWR, 0666)
if err != nil{
fmt.Println("创建失败")
}else{
fmt.Println(fp)
}
defer func() {
if err := fp.Close(); err != nil{
fmt.Println("关闭文件失败")
}
}()
w := bufio.NewWriter(fp)
len , err := w.WriteString("\r\n123456")
if err != nil{
fmt.Println("写入数据失败")
}else{
fmt.Println("写入成功, 写入了", len, "个字节")
}
w.Flush()
文件的拷贝
- io包中的copy函数
- 函数接收两个参数,第一个参数是被写入的文件,第二个参数是写入的东西所在的文件
文件判断
- os包里有个函数叫Stat()
- func Stat(name string) (FileInfo, error)
- 函数接收一个字符串,是文件地址的字符串,返回一个文件句柄和错误信息,FileInfo本质上是一个接口,我们可以通过第一个返回值.结构体名称的格式来查看文件的名称,大小,模式,是否为目录等等...
type FileInfo interface {
Name() string // base name of the file
Size() int64 // length in bytes for regular files; system-dependent for others
Mode() FileMode // file mode bits
ModTime() time.Time // modification time
IsDir() bool // abbreviation for Mode().IsDir()
Sys() interface{} // underlying data source (can return nil)
}
finfo, err := os.Stat("D:/WWW")
if err != nil {
fmt.Println(err)
}else{
//fmt.Println(finfo)
fmt.Println(finfo.Name())
fmt.Println(finfo.Size())
fmt.Println(finfo.ModTime())
fmt.Println(finfo.IsDir())
}