28

Golang:File 文件操作

 3 years ago
source link: https://studygolang.com/articles/30881
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

首先,file 类是在 os 包中的,封装了底层的文件描述符和相关信息,同时封装了 Read 和 Write 的实现。

FileInfo 接口

FileInfo 接口中定义了 File 信息相关的方法。

type FileInfo interface {
    Name() string       // base name of the file 文件名.扩展名 aa.txt
    Size() int64        // 文件大小,字节数 12540
    Mode() FileMode     // 文件权限 -rw-rw-rw-
    ModTime() time.Time // 修改时间 2020-09-23 16:30:53 +0800 CST
    IsDir() bool        // 是否文件夹
    Sys() interface{}   // 基础数据源接口(can return nil)
}

权限

至于操作权限 perm,除非创建文件时才需要指定,不需要创建新文件时可以将其设定为0。虽然 Golang 语言给 perm 权限设定了很多的常量,但是习惯上也可以直接使用数字,如 0666 (具体含义和 Unix 系统的一致)。

权限控制:

linux 下有2种文件权限表示方式,即“符号表示”和“八进制表示”。

(1)符号表示方式:
-      ---         ---        ---
type   owner       group      others
文件的权限是这样子分配的 读 写 可执行 分别对应的是 r w x 如果没有那一个权限,用 - 代替
(-文件 d目录 |连接符号)
例如:-rwxr-xr-x

(2)八进制表示方式: 
r ——> 004
w ——> 002
x ——> 001
- ——> 000

0755
0777
0555
0444
0666

示例代码:

package main

import (
    "os"
    "fmt"
)

func main() {
    /*
    FileInfo:文件信息
        interface
            Name(),文件名
            Size(),文件大小,字节为单位
            IsDir(),是否是目录
            ModTime(),修改时间
            Mode(),权限

     */
    fileInfo,err :=  os.Stat("/Users/ruby/Documents/pro/a/aa.txt")
    if err != nil{
        fmt.Println("err :",err)
        return
    }
    fmt.Printf("%T\n",fileInfo)
    //文件名
    fmt.Println(fileInfo.Name())
    //文件大小
    fmt.Println(fileInfo.Size())
    //是否是目录
    fmt.Println(fileInfo.IsDir()) //IsDirectory
    //修改时间
    fmt.Println(fileInfo.ModTime())
    //权限
    fmt.Println(fileInfo.Mode()) //-rw-r--r--
}

运行结果:

YnY7JfN.png!mobile

文件信息示例代码运行结果

File 操作

type File
//File代表一个打开的文件对象。

func Create(name string) (file *File, err error)
//Create采用模式0666(任何人都可读写,不可执行)创建一个名为name的文件,如果文件已存在会截断它(为空文件)。如果成功,返回的文件对象可用于I/O;对应的文件描述符具有O_RDWR模式。如果出错,错误底层类型是*PathError。

func Open(name string) (file *File, err error)
//Open打开一个文件用于读取。如果操作成功,返回的文件对象的方法可用于读取数据;对应的文件描述符具有O_RDONLY模式。如果出错,错误底层类型是*PathError。

func OpenFile(name string, flag int, perm FileMode) (file *File, err error)
//OpenFile是一个更一般性的文件打开函数,大多数调用者都应用Open或Create代替本函数。它会使用指定的选项(如O_RDONLY等)、指定的模式(如0666等)打开指定名称的文件。如果操作成功,返回的文件对象可用于I/O。如果出错,错误底层类型是*PathError。

func NewFile(fd uintptr, name string) *File
//NewFile使用给出的Unix文件描述符和名称创建一个文件。

func Pipe() (r *File, w *File, err error)
//Pipe返回一对关联的文件对象。从r的读取将返回写入w的数据。本函数会返回两个文件对象和可能的错误。

func (f *File) Name() string
//Name方法返回(提供给Open/Create等方法的)文件名称。

func (f *File) Stat() (fi FileInfo, err error)
//Stat返回描述文件f的FileInfo类型值。如果出错,错误底层类型是*PathError。

func (f *File) Fd() uintptr
//Fd返回与文件f对应的整数类型的Unix文件描述符。

func (f *File) Chdir() error
//Chdir将当前工作目录修改为f,f必须是一个目录。如果出错,错误底层类型是*PathError。

func (f *File) Chmod(mode FileMode) error
//Chmod修改文件的模式。如果出错,错误底层类型是*PathError。

func (f *File) Chown(uid, gid int) error
//Chown修改文件的用户ID和组ID。如果出错,错误底层类型是*PathError。

func (f *File) Close() error
//Close关闭文件f,使文件不能用于读写。它返回可能出现的错误。

func (f *File) Readdir(n int) (fi []FileInfo, err error)
//Readdir读取目录f的内容,返回一个有n个成员的[]FileInfo,这些FileInfo是被Lstat返回的,采用目录顺序。对本函数的下一次调用会返回上一次调用剩余未读取的内容的信息。如果n>0,Readdir函数会返回一个最多n个成员的切片。这时,如果Readdir返回一个空切片,它会返回一个非nil的错误说明原因。如果到达了目录f的结尾,返回值err会是io.EOF。如果n<=0,Readdir函数返回目录中剩余所有文件对象的FileInfo构成的切片。此时,如果Readdir调用成功(读取所有内容直到结尾),它会返回该切片和nil的错误值。如果在到达结尾前遇到错误,会返回之前成功读取的FileInfo构成的切片和该错误。

func (f *File) Readdirnames(n int) (names []string, err error)
//Readdir读取目录f的内容,返回一个有n个成员的[]string,切片成员为目录中文件对象的名字,采用目录顺序。对本函数的下一次调用会返回上一次调用剩余未读取的内容的信息。如果n>0,Readdir函数会返回一个最多n个成员的切片。这时,如果Readdir返回一个空切片,它会返回一个非nil的错误说明原因。如果到达了目录f的结尾,返回值err会是io.EOF。如果n<=0,Readdir函数返回目录中剩余所有文件对象的名字构成的切片。此时,如果Readdir调用成功(读取所有内容直到结尾),它会返回该切片和nil的错误值。如果在到达结尾前遇到错误,会返回之前成功读取的名字构成的切片和该错误。

func (f *File) Truncate(size int64) error
//Truncate改变文件的大小,它不会改变I/O的当前位置。 如果截断文件,多出的部分就会被丢弃。如果出错,错误底层类型是*PathError。

打开模式:

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  // 如果可能,打开时清空文件
)

文件操作实例:

package main

import (
    "fmt"
    "path/filepath"
    "path"
    "os"
)

func main() {
    /*
    文件操作:
    1.路径:
        相对路径:relative
            ab.txt
            相对于当前工程
        绝对路径:absolute
            /Users/ruby/Documents/pro/a/aa.txt

        .当前目录
        ..上一层
    2.创建文件夹,如果文件夹存在,创建失败
        os.MkDir(),创建一层
        os.MkDirAll(),可以创建多层

    3.创建文件,Create采用模式0666(任何人都可读写,不可执行)创建一个名为name的文件,如果文件已存在会截断它(为空文件)
        os.Create(),创建文件

    4.打开文件:让当前的程序,和指定的文件之间建立一个连接
        os.Open(filename)
        os.OpenFile(filename,mode,perm)

    5.关闭文件:程序和文件之间的链接断开。
        file.Close()

    5.删除文件或目录:慎用,慎用,再慎用
        os.Remove(),删除文件和空目录
        os.RemoveAll(),删除所有
     */
     //1.路径
     fileName1:="/Users/ruby/Documents/pro/a/aa.txt"
     fileName2:="bb.txt"
     fmt.Println(filepath.IsAbs(fileName1)) //true
     fmt.Println(filepath.IsAbs(fileName2)) //false
     fmt.Println(filepath.Abs(fileName1))
     fmt.Println(filepath.Abs(fileName2)) // /Users/ruby/go/src/l_file/bb.txt

     fmt.Println("获取父目录:",path.Join(fileName1,".."))

     //2.创建目录
     //err := os.Mkdir("/Users/ruby/Documents/pro/a/bb",os.ModePerm)
     //if err != nil{
     // fmt.Println("err:",err)
     // return
     //}
     //fmt.Println("文件夹创建成功。。")
     //err :=os.MkdirAll("/Users/ruby/Documents/pro/a/cc/dd/ee",os.ModePerm)
     //if err != nil{
     // fmt.Println("err:",err)
     // return
     //}
     //fmt.Println("多层文件夹创建成功")

     //3.创建文件:Create采用模式0666(任何人都可读写,不可执行)创建一个名为name的文件,如果文件已存在会截断它(为空文件)
     //file1,err :=os.Create("/Users/ruby/Documents/pro/a/ab.txt")
     //if err != nil{
     // fmt.Println("err:",err)
     // return
     //}
     //fmt.Println(file1)

     //file2,err := os.Create(fileName2)//创建相对路径的文件,是以当前工程为参照的
     //if err != nil{
     // fmt.Println("err :",err)
     // return
     //}
     //fmt.Println(file2)

     //4.打开文件:
     //file3 ,err := os.Open(fileName1) //只读的
     //if err != nil{
     // fmt.Println("err:",err)
     // return
     //}
     //fmt.Println(file3)
    /*
    第一个参数:文件名称
    第二个参数:文件的打开方式
        const (
    // Exactly one of O_RDONLY, O_WRONLY, or O_RDWR must be specified.
        O_RDONLY int = syscall.O_RDONLY // open the file read-only.
        O_WRONLY int = syscall.O_WRONLY // open the file write-only.
        O_RDWR   int = syscall.O_RDWR   // open the file read-write.
        // The remaining values may be or'ed in to control behavior.
        O_APPEND int = syscall.O_APPEND // append data to the file when writing.
        O_CREATE int = syscall.O_CREAT  // create a new file if none exists.
        O_EXCL   int = syscall.O_EXCL   // used with O_CREATE, file must not exist.
        O_SYNC   int = syscall.O_SYNC   // open for synchronous I/O.
        O_TRUNC  int = syscall.O_TRUNC  // truncate regular writable file when opened.
    )
    第三个参数:文件的权限:文件不存在创建文件,需要指定权限
     */
     //file4,err := os.OpenFile(fileName1,os.O_RDONLY|os.O_WRONLY,os.ModePerm)
     //if err != nil{
     // fmt.Println("err:",err)
     // return
     //}
     //fmt.Println(file4)

     //5关闭文件,
     //file4.Close()

     //6.删除文件或文件夹:
     //删除文件
    //err :=  os.Remove("/Users/ruby/Documents/pro/a/aa.txt")
    //if err != nil{
    //  fmt.Println("err:",err)
    //  return
    //}
    //fmt.Println("删除文件成功。。")
    //删除目录
    err :=  os.RemoveAll("/Users/ruby/Documents/pro/a/cc")
    if err != nil{
        fmt.Println("err:",err)
        return
    }
    fmt.Println("删除目录成功。。")
}

判断文件是否存在

Golang 判断文件或文件夹是否存在的方法为使用 os.Stat() 函数返回的错误值进行判断。

  1. 如果返回的错误为 nil,说明文件或文件夹存在
  2. 如果返回的错误类型使用 os.IsNotExist() 判断为 true,说明文件或文件夹不存在

示例代码:

package main
import (
    "log"
    "os"
)

func main() {
    fileInfo,err:=os.Stat("/Users/ruby/Documents/pro/a/aa.txt")
    if err!=nil{
        if os.IsNotExist(err){
            log.Fatalln("file does not exist")
        }
    }
    log.Println("file does exist. file information:")
    log.Println(fileInfo)
}

有疑问加站长微信联系

iiUfA3j.png!mobile

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK