go语言提供了大量的包,基于这些包我们可以完成很多有意思的事情,本节我们就来看看如何利用go语言来遍历文件。
常规方法(不使用path/filepath包)
比较直观的方式是,按照某个目录递归的方式便利文件:
func walkDir(dirpath string, depth int){
if depth > DEPTH{//大于设定的深度
return
}
files, err := ioutil.ReadDir(dirpath)//读取目录下文件
if err != nil{
return
}
for _, file := range files{
if file.IsDir(){
walkDir(dirpath + "/" + file.Name(), depth+1)
continue
}else{
.....
}
}
}
- 先利用
ioutil
包中的ReadDir
方法读取该目录下Dir信息 - 根据返回的
file
信息判断其是否为目录
- 如果是目录则递归调用
walkDir
方法 - 否则对文件进行处理
- 如果是目录则递归调用
这就完成了对文件的一个遍历,这样的遍历操作简单。当然由于递归调用,因此比较消耗内存。
go的filepath包
filepath包实现了兼容各个操作系统的文件路径实用操作方法
本次用到的主要是两个方法
方法 | 定义 |
---|---|
WalkFunc | type WalkFunc func(path string, info os.FileInfo, err error) erro |
Walk | func Walk(root string, walkFc WalkFunc) error |
我们可以看到其实在Walk里面有一个WalkFunc方法的调用,其作用是用来过滤。
Walk(root stirng, walkFn WalkFunc) error方法
walk方法会遍历root下的所有文件(包含root)并对每一个目录和文件都调用walkFunc方法。在访问文件和目录时发生的错误都会通过error参数传递给WalkFunc方法。文件是按照词法顺序进行遍历的,这个通常让输出更漂亮,但是也会导致处理非常大的目录时效率会降低。另外,walk函数不会遍历符号链接。
WalkFunc(path string, info os.FileInfo, err error) error函数
Walk函数在遍历文件时调用。调用时将参数传递给path,这是一个绝对路径,也就是Walk函数中的root作为前缀。将root + 文件名作为path传递给WalkFunc函数。例如在"Dir"目录下遍历到"a"文件,则path="Dir/a"
Info是path所指向文件的文件信息。如果在遍历过程中出现了问题,传入参数err会描述这个问题。WalkFunc函数可以处理这个问题,Walk将不会再深入该目录。如果函数会返回一个错误,Walk函数会终止执行;只有一个例外,我们也通常用这个来跳过某些目录。当WalkFunc的返回值是filepaht.SkipDir时,Walk将会跳过这个目录,照常执行下一个文件。
例子:
import "path/filepath"
func walkDir(dir string){
files, err := ioutil.ReadDir(dir)
if err != nil{
...
}
for _, file := ranges files{
filename := file.Name()
filepath.Walk(filename,func(path string, fi os.FileInfo, err error)error{
depth := strings.Count(path,"/") - strings.Count(filename,"/")
if depth > DEPTH{
return filepath.SkipDir
}
if err != nil{
//处理文件读取异常
}
if fi.IsDir(){
满足条件不用管
不满足条件
return filepath.SkipDir
}
})
}
}
有疑问加站长微信联系(非本文作者)