hapiman / jsrice

A common utils using in javascript
0 stars 0 forks source link

Golang文件操作 #35

Open hapiman opened 6 years ago

hapiman commented 6 years ago

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

目录操作

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

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是权限。
``` go
  // 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 在条件允许的情况下,打开文件时候清空文件内容

写文件

写文件函数:

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中
读文件的示例代码:
``` golang 
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)
}