Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Golang文件操作 #35

Open
hapiman opened this issue Jan 1, 2018 · 0 comments
Open

Golang文件操作 #35

hapiman opened this issue Jan 1, 2018 · 0 comments

Comments

@hapiman
Copy link
Owner

hapiman commented Jan 1, 2018

在写程序的时候,我们经常会遇到创建文件与目录,对文件(夹)编辑等操作,下面就这些操作做一个大致介绍并通过示例示范如何使用。

目录操作

文件目录操作的大多数函数都是在os包里面,下面列举了几个目录操作的:

  • func Mkdir(name string, perm FileMode) error
    创建目录,权限设置是perm,例如0777
  • func MkdirAll(path string, perm FileMode) error
    创建目录,如果路径中有不存在的中间目录,则新建不存在的中间目录,从而尽量保证目录创建成功
  • func Remove(name string) error
    删除文件或空目录
  • func RemoveAll(path string) error
    删除目录及目录下所有的子文件与目录
  • func Readdir(n int) (fi []FileInfo, err error)
    读取一个目录中文件列表
    如果n > 0,则至多读取并返回n个文件信息
    如果n <= 0,则读取所有的文件列表信息
    下面是演示代码:
package main

import (
    "fmt"
    "os"
)

func main() {
    rootPath := "root"
    err := os.Mkdir(rootPath, 0777)
    if err != nil {
        fmt.Println("mkdir root failed!")
        return
    }
    rrPath := "root/test1/test2"
    err := os.MkdirAll(rrPath, 0777)
    if err != nil {
        fmt.Println("mkdir root/test1/test2 failed!")
        return
    }
    err := os.Remove(rootPath)
    if err != nil {
        fmt.Println(err)
    }
    err := os.RemoveAll(rootPath)
    if err != nil {
        fmt.Println(err)
    }    
}

文件操作

一般文件操作包括:新建、打开、读写及删除。
文件操作很多情况下需要注意权限,默认使用unix文件权限模型。

新建与打开文件
新建文件可以通过如下两个方法:

  • func Create(name string) (file *File, err error)
    根据文件名创建新的文件或者清空已存在文件,返回一个文件对象,默认权限是0666的文件,返回的文件对象是可读写的。

  • func NewFile(fd uintptr, name string) *File
    根据文件描述符创建相应的文件,返回一个文件对象
    通过如下两个方法来打开文件:

  • func Open(name string) (file *File, err error)
    该方法以只读方式打开一个文件,内部实现其实调用了OpenFile。

  • func OpenFile(name string, flag int, perm uint32) (file *File, err error)
    打开某一个文件,flag是打开的方式,只读、读写等,perm是权限。

  // flag 可取值:
  O_RDONLY   // open the file read-only 以只读方式打开
  O_WRONLY   // open the file write-only 以只写的方式打开
  O_RDWR     // open the file read-write 以读写的方式打开
  O_APPEND   // append data to the file  添加内容到文件,不能单独使用,需要在可写条件下
  O_CREATE   // create a new file if none exists 如果文件不存在,则创建一个新文件
  O_EXCL     // used with O_CREATE, file must not exist 和标志O_CREATE一起用,文件必须是不存在的
  O_SYNC     // open for synchronous I/O 以同步I/O的方式打开
  O_TRUNC    // if possible, truncate file when opened 在条件允许的情况下,打开文件时候清空文件内容

写文件

写文件函数:

  • func (file *File) Write(b []byte) (n int, err error)
    写入byte数组类型的信息到文件
  • func (file *File) WriteAt(b []byte, off int64) (n int, err error)
    在指定偏移位置off处开始写入byte数组类型的信息
  • func (file *File) WriteString(s string) (ret int, err error)
    写入字符串s到文件
    写文件的示例代码
package main

import (
    "fmt"
    "os"
)

func main() {
    userFile := "test.txt"
    // 以只写且添加的方式打开文件,文件权限为0666
    fout, err := os.OpenFile(userFile, os.O_WRONLY|os.O_APPEND, 0666)
    if err != nil {
        fmt.Println(userFile, err)
        return
    }
    defer fout.Close()

    for i := 0; i < 10; i++ {
        fout.WriteString("Just a test!\r\n")
        fout.Write([]byte("Just a test!\r\n"))
    }
}

读文件

读文件函数:

  • func (file *File) Read(b []byte) (n int, err error)
    读取数据到b中
  • func (file *File) ReadAt(b []byte, off int64) (n int, err error)
    从off开始读取数据到b中
    读文件的示例代码:
package main

import (
    "fmt"
    "os"
)

func main() {
    userFile := "test.txt"
    fl, err := os.Open(userFile)
    if err != nil {
        fmt.Println(userFile, err)
        return
    }
    defer fl.Close()

    buf := make([]byte, 1024)
    for {
        n, _ := fl.Read(buf)
        if 0 == n {
            break
        }
        os.Stdout.Write(buf[:n])
    }
}

删除文件
Go语言里面删除文件和删除文件夹是同一个函数,参见上面删除目录操作

检测文件或者目录是否存在
Golang默认没有一个检测路径是否存在的函数,但是可以用其它方式进行检测。示例:

func exists(path string) (bool, error) {

    _, err := os.Stat(path)

    if err == nil {
        return true, nil
    }

    // 检测是否为路径不存在的错误
    if os.IsNotExist(err) {
        return false, nil
    }

    return true, err
}

小例子
读取一个目录,并递归列出所有文件

package main

import (
    "fmt"
    "log"
    "os"
    "path"
    "strings"
)

func printFile(file os.FileInfo, root string) {
    // 文件全路径
    filename := path.Join(root, file.Name())
    fmt.Println(filename)
}

func printDir(dir []os.FileInfo, root string, deep int) {
    // 如果深度超过3,则返回
    // 此处仅为测试时防止控制台打印输出太多
    if deep > 3 {
        return
    }

    for _, v := range dir {

        name := v.Name()

        // 忽略.和..
        if strings.HasPrefix(name, ".") {
            continue
        }

        isDir := v.IsDir()
        if !isDir {
            printFile(v, root)
        } else {
            _path := path.Join(root, name)
            // 打印目录名称
            fmt.Println(_path)
            _dirpath, err := os.Open(_path)
            if err != nil {
                log.Fatal(err)
            }
            defer _dirpath.Close()

            _dir, err := _dirpath.Readdir(0)
            if err != nil {
                log.Fatal(err)
            }
            // 递归目录
            printDir(_dir, _path, deep+1)
        }
  }
}

func main() {
    // 读取go目录, just for example!
    rootPath := "/usr/local/go"
    rootDir, err := os.Open(rootPath)
    if err != nil {
        log.Fatal(err)
    }
    defer rootDir.Close()

    fs, err := rootDir.Readdir(0)
    printDir(fs, rootPath, 0)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant