Skip to content

Fileutil

fileutil 包支持文件基本操作。

源码:

用法:

go
import (
    "github.com/duke-git/lancet/v2/fileutil"
)

目录

文档

ClearFile

清空文件内容

函数签名:

go
func ClearFile(path string) error

示例:运行

go
package main

import (
    "fmt"
    "github.com/duke-git/lancet/v2/fileutil"
)

func main() {
    err := fileutil.ClearFile("./test.txt")
    if err != nil {
        fmt.Println(err)
    }
}

CreateFile

创建文件,创建成功返回true, 否则返回false

函数签名:

go
func CreateFile(path string) bool

示例:运行

go
package main

import (
    "fmt"
    "github.com/duke-git/lancet/v2/fileutil"
)

func main() {
    isCreatedSucceed := fileutil.CreateFile("./test.txt")
    fmt.Println(isCreatedSucceed)
}

CreateDir

使用绝对路径创建嵌套目录,例如/a/, /a/b

函数签名:

go
func CreateDir(absPath string) error

示例:运行

go
package main

import (
    "fmt"
    "github.com/duke-git/lancet/v2/fileutil"
)

func main() {
    err := fileutil.CreateDir("/a/b") // will create folder /a/b
    fmt.Println(err)
}

CopyFile

拷贝文件,会覆盖原有的文件

函数签名:

go
func CopyFile(srcPath string, dstPath string) error

示例:运行

go
package main

import (
    "fmt"
    "github.com/duke-git/lancet/v2/fileutil"
)

func main() {
    err := fileutil.CopyFile("./test.txt", "./test_copy.txt")
    if err != nil {
        fmt.Println(err)
    }
}

CopyDir

拷贝文件夹到目标路径,会递归复制文件夹下所有的文件及文件夹,并且访问权限也与源文件夹保持一致。当dstPath存在时会返回error

函数签名:

go
func CopyDir(srcPath string, dstPath string) error

示例:运行

go
package main

import (
    "fmt"
    "github.com/duke-git/lancet/v2/fileutil"
)

func main() {
    err := fileutil.CopyFile("./test_src", "./test_dest")
    if err != nil {
        fmt.Println(err)
    }
}

CurrentPath

返回当前位置的绝对路径。

函数签名:

go
func CurrentPath() string

示例:运行

go
package main

import (
    "fmt"
    "github.com/duke-git/lancet/v2/fileutil"
)

func main() {
    absPath := CurrentPath()
    fmt.Println(absPath)
}

FileMode

获取文件mode信息

函数签名:

go
func FileMode(path string) (fs.FileMode, error)

示例:运行

go
package main

import (
    "fmt"
    "github.com/duke-git/lancet/v2/fileutil"
)

func main() {
    mode, err := fileutil.FileMode("./test.txt")
    if err != nil {
        fmt.Println(err)
    }
    fmt.Println(mode)
}

MiMeType

获取文件mime类型, 'file'参数的类型必须是string或者*os.File

函数签名:

go
func MiMeType(file any) string

示例:运行

go
package main

import (
    "fmt"
    "os"
    "github.com/duke-git/lancet/v2/fileutil"
)

func main() {
    type1 := fileutil.MiMeType("./test.txt")
    fmt.Println(type1) //text/plain; charset=utf-8

    f, _ := os.Open("./file.go")
    type2 := fileutil.MiMeType(f)
    fmt.Println(type2) //text/plain; charset=utf-8
}

IsExist

判断文件或目录是否存在

函数签名:

go
func IsExist(path string) bool

示例:运行

go
package main

import (
    "fmt"
    "github.com/duke-git/lancet/v2/fileutil"
)

func main() {
    fileutil.CreateFile("./test.txt")
    isFileExist := fileutil.IsExist("./test.txt")
    fmt.Println(isFileExist) //true
}

判断文件是否是符号链接

函数签名:

go
func IsLink(path string) bool

示例:运行

go
package main

import (
    "fmt"
    "github.com/duke-git/lancet/v2/fileutil"
)

func main() {
    isLinkFile := fileutil.IsLink("./test.txt")
    fmt.Println(isLinkFile) //false
}

IsDir

判断参数是否是目录

函数签名:

go
func IsDir(path string) bool

示例:运行

go
package main

import (
    "fmt"
    "github.com/duke-git/lancet/v2/fileutil"
)

func main() {
    isDir := fileutil.IsDir("./")
    fmt.Println(isDir) //true

    isDir = fileutil.IsDir("./test.txt")
    fmt.Println(isDir) //false
}

ListFileNames

返回目录下所有文件名

函数签名:

go
func ListFileNames(path string) ([]string, error)

示例:运行

go
package main

import (
    "fmt"
    "github.com/duke-git/lancet/v2/fileutil"
)

func main() {
    fileNames, _ := fileutil.ListFileNames("./")
    fmt.Println(fileNames)
}

RemoveFile

删除文件

函数签名:

go
func RemoveFile(path string) error

示例:运行

go
package main

import (
    "fmt"
    "github.com/duke-git/lancet/v2/fileutil"
)

func main() {
    err := fileutil.RemoveFile("./test.txt")
    if err != nil {
        fmt.Println(err)
    }
}

ReadFileToString

读取文件内容并返回字符串

函数签名:

go
func ReadFileToString(path string) (string, error)

示例:运行

go
package main

import (
    "fmt"
    "os"
    "github.com/duke-git/lancet/v2/fileutil"
)

func main() {
    path := "./test.txt"
    fileutil.CreateFile(path)

    f, _ := os.OpenFile(path, os.O_WRONLY|os.O_TRUNC, 0777)
    f.WriteString("hello world")

    content, _ := fileutil.ReadFileToString(path)
    fmt.Println(content) //hello world
}

ReadFileByLine

按行读取文件内容,返回字符串切片包含每一行

函数签名:

go
func ReadFileByLine(path string)([]string, error)

示例:运行

go
package main

import (
    "fmt"
    "os"
    "github.com/duke-git/lancet/v2/fileutil"
)

func main() {
    path := "./text.txt"
    fileutil.CreateFile(path)

    f, _ := os.OpenFile(path, os.O_WRONLY|os.O_TRUNC, 0777)
    defer f.Close()
    f.WriteString("hello\nworld")

    contents, _ := fileutil.ReadFileByLine(path)
    fmt.Println(contents) //[]string{"hello", "world"}
}

Zip

zip压缩文件, fpath参数可以是文件或目录

函数签名:

go
func Zip(fpath string, destPath string) error

示例:运行

go
package main

import (
    "fmt"
    "github.com/duke-git/lancet/v2/fileutil"
)

func main() {
    err := fileutil.Zip("./test.txt", "./test.zip")
    if err != nil {
        fmt.Println(err)
    }
}

ZipAppendEntry

通过将单个文件或目录追加到现有的zip文件

函数签名:

go
func ZipAppendEntry(fpath string, destPath string) error

示例:运行

go
package main

import (
    "fmt"
    "github.com/duke-git/lancet/v2/fileutil"
)

func main() {
    err := fileutil.ZipAppendEntry("./test.txt", "./test.zip")
    if err != nil {
        fmt.Println(err)
    }
}

UnZip

zip解压缩文件并保存在目录中

函数签名:

go
func UnZip(zipFile string, destPath string) error

示例:运行

go
package main

import (
    "fmt"
    "github.com/duke-git/lancet/v2/fileutil"
)

func main() {
    err := fileutil.Zip("./test.zip", "./unzip/test.txt")
    if err != nil {
        fmt.Println(err)
    }
}

IsZipFile

判断文件是否是zip压缩文件。

函数签名:

go
func IsZipFile(filepath string) bool

示例:运行

go
package main

import (
    "fmt"
    "github.com/duke-git/lancet/v2/fileutil"
)

func main() {
    isZip := fileutil.IsZipFile("./zipfile.zip")
    fmt.Println(isZip)
}

FileSize

返回文件字节大小。

函数签名:

go
func FileSize(path string) (int64, error)

示例:运行

go
package main

import (
    "fmt"
    "github.com/duke-git/lancet/v2/fileutil"
)

func main() {
    size, err := fileutil.FileSize("./testdata/test.txt")

    fmt.Println(size)
    fmt.Println(err)

    // Output:
    // 20
    // <nil>
}

MTime

返回文件修改时间(unix timestamp).

函数签名:

go
func MTime(filepath string) (int64, error)

示例:运行

go
package main

import (
    "fmt"
    "github.com/duke-git/lancet/v2/fileutil"
)

func main() {
    mtime, err := fileutil.MTime("./testdata/test.txt")

    fmt.Println(mtime)
    fmt.Println(err)

    // Output:
    // 1682391110
    // <nil>
}

Sha

返回文件sha值,参数`shaType` 应传值为: 1, 256,512.

函数签名:

go
func Sha(filepath string, shaType ...int) (string, error)

示例:运行

go
package main

import (
    "fmt"
    "github.com/duke-git/lancet/v2/fileutil"
)

func main() {
    sha1, err := fileutil.Sha("./testdata/test.txt", 1)
    sha256, _ := fileutil.Sha("./testdata/test.txt", 256)
    sha512, _ := fileutil.Sha("./testdata/test.txt", 512)

    fmt.Println(sha1)
    fmt.Println(sha256)
    fmt.Println(sha512)
    fmt.Println(err)

    // Output:
    // dda3cf10c5a6ff6c6659a497bf7261b287af2bc7
    // aa6d0a3fbc3442c228d606da09e0c1dc98c69a1cac3da1909199e0266171df35
    // d22aba2a1b7a2e2f512756255cc1c3708905646920cb1eb95e45b531ba74774dbbb89baebf1f716220eb9cf4908f1cfc5b2a01267704d9a59f59d77cab609870
    // <nil>
}

ReadCsvFile

读取csv文件内容到切片

函数签名:

go
func ReadCsvFile(filepath string, delimiter ...rune) ([][]string, error)

示例:运行

go
package main

import (
    "fmt"
    "github.com/duke-git/lancet/v2/fileutil"
)

func main() {
    content, err := fileutil.ReadCsvFile("./testdata/test.csv")

    fmt.Println(content)
    fmt.Println(err)

    // Output:
    // [[Bob  12  male] [Duke  14  male] [Lucy  16  female]]
    // <nil>
}

WriteCsvFile

向csv文件写入内容。

函数签名:

go
func WriteCsvFile(filepath string, records [][]string, append bool, delimiter ...rune) error

示例:运行

go
package main

import (
    "fmt"
    "github.com/duke-git/lancet/v2/fileutil"
)

func main() {
    fpath := "./test.csv"
    fileutil.CreateFile(fpath)

    f, _ := os.OpenFile(fpath, os.O_WRONLY|os.O_TRUNC, 0777)
    defer f.Close()

    data := [][]string{
        {"Lili", "22", "female"},
        {"Jim", "21", "male"},
    }
    err := fileutil.WriteCsvFile(fpath, data, false)

    if err != nil {
        return
    }

    content, err := fileutil.ReadCsvFile(fpath)

    if err != nil {
        return
    }
    fmt.Println(content)

    // Output:
    // [[Lili 22 female] [Jim 21 male]]
}

WriteMapsToCsv

将map切片写入csv文件中。

函数签名:

go
// filepath: CSV文件路径。
// records: 写入文件的map切片。map值必须为基本类型。会以map键的字母顺序写入。
// appendToExistingFile: 是否为追加写模式。
// delimiter: CSV文件分割符。
// headers: CSV文件表头顺序(需要与map key保持一致),不指定时按字母排序。
func WriteMapsToCsv(filepath string, records []map[string]any, appendToExistingFile bool, delimiter rune, headers ...[]string) error

示例:运行

go
package main

import (
    "fmt"
    "github.com/duke-git/lancet/v2/fileutil"
)

func main() {
    fpath := "./test.csv"
    fileutil.CreateFile(fpath)

    f, _ := os.OpenFile(fpath, os.O_WRONLY|os.O_TRUNC, 0777)
    defer f.Close()

    records := []map[string]any{
        {"Name": "Lili", "Age": "22", "Gender": "female"},
        {"Name": "Jim", "Age": "21", "Gender": "male"},
    }

    headers := []string{"Name", "Age", "Gender"}
    err := fileutil.WriteMapsToCsv(csvFilePath, records, false, ';', headers)

    if err != nil {
        log.Fatal(err)
    }

    content, err := fileutil.ReadCsvFile(csvFilePath, ';')

    fmt.Println(content)

    // Output:
    // [[Name Age Gender] [Lili 22 female] [Jim 21 male]]
}

WriteBytesToFile

将bytes写入文件。

函数签名:

go
func WriteBytesToFile(filepath string, content []byte) error

示例:运行

go
package main

import (
    "fmt"
    "github.com/duke-git/lancet/v2/fileutil"
)

func main() {
    filepath := "./bytes.txt"

    file, err := os.Create(filepath)
    if err != nil {
        return
    }

    defer file.Close()

    err = fileutil.WriteBytesToFile(filepath, []byte("hello"))
    if err != nil {
        return
    }

    content, err := fileutil.ReadFileToString(filepath)
    if err != nil {
        return
    }

    os.Remove(filepath)

    fmt.Println(content)

    // Output:
    // hello
}

WriteStringToFile

将字符串写入文件。

函数签名:

go
func WriteStringToFile(filepath string, content string, append bool) error

示例:运行

go
package main

import (
    "fmt"
    "github.com/duke-git/lancet/v2/fileutil"
)

func main() {
    filepath := "./test.txt"

    file, err := os.Create(filepath)
    if err != nil {
        return
    }

    defer file.Close()

    err = fileutil.WriteStringToFile(filepath, "hello", true)
    if err != nil {
        return
    }

    content, err := fileutil.ReadFileToString(filepath)
    if err != nil {
        return
    }

    os.Remove(filepath)

    fmt.Println(content)

    // Output:
    // hello
}

ReadFile

读取文件或者URL。

函数签名:

go
func ReadFile(path string) (reader io.ReadCloser, closeFn func(), err error)

示例:运行

go
package main

import (
    "fmt"
    "github.com/duke-git/lancet/v2/fileutil"
)

func main() {
    reader, fn, err := fileutil.ReadFile("https://httpbin.org/robots.txt")
    if err != nil {
        return
    }
    defer fn()

    dat, err := io.ReadAll(reader)
    if err != nil {
        return
    }
    
    fmt.Println(string(dat))
    
    // Output:
    // User-agent: *
    // Disallow: /deny
}

ChunkRead

从文件的指定偏移读取块并返回块内所有行。

函数签名:

go
func ChunkRead(file *os.File, offset int64, size int, bufPool *sync.Pool) ([]string, error)

示例:运行

go
package main

import (
    "fmt"
    "github.com/duke-git/lancet/v2/fileutil"
)

func main() {
    const mb = 1024 * 1024
    const defaultChunkSizeMB = 100 

    // test1.csv file content:
    // Lili,22,female
    // Jim,21,male
    filePath := "./testdata/test1.csv" // 替换为你的文件路径
    f, err := os.Open(filePath)
    if err != nil {
        return
    }

    defer f.Close()

    var bufPool = sync.Pool{
        New: func() interface{} {
            return make([]byte, 0, defaultChunkSizeMB*mb)
        },
    }

    lines, err := fileutil.ChunkRead(f, 0, 100, &bufPool)
    if err != nil {
        return
    }

    fmt.Println(lines[0])
    fmt.Println(lines[1])

    // Output:
    // Lili,22,female
    // Jim,21,male
}

ParallelChunkRead

并行读取文件并将每个块的行发送到指定通道。

函数签名:

go
// filePath:文件路径
// chunkSizeMB: 分块的大小(单位MB,设置为0时使用默认100MB),设置过大反而不利,视情调整
// maxGoroutine: 并发读取分块的数量,设置为0时使用CPU核心数
// linesCh: 用于接收返回结果的通道。
func ParallelChunkRead(filePath string, linesCh chan<- []string, chunkSizeMB, maxGoroutine int) error

示例:运行

go
package main

import (
    "fmt"
    "github.com/duke-git/lancet/v2/fileutil"
)

func main() {
    const mb = 1024 * 1024
    const defaultChunkSizeMB = 100 // 默认值

    numParsers := runtime.NumCPU()

    linesCh := make(chan []string, numParsers)
    
    // test1.csv file content:
    // Lili,22,female
    // Jim,21,male
    filePath := "./testdata/test1.csv"

    go fileutil.ParallelChunkRead(filePath, linesCh, defaultChunkSizeMB, numParsers)

    var totalLines int
    for lines := range linesCh {
        totalLines += len(lines)

        for _, line := range lines {
            fmt.Println(line)
        }
    }

    fmt.Println(totalLines)

    // Output:
    // Lili,22,female
    // Jim,21,male
    // 2
}