filepath 文件路径处理
Go语言提供了filepath模块用于处理文件路径字符串,对于文件路径的处理,我们应该使用filepath而非自己手动切割和拼接字符串。filepath有更好的跨平台兼容性,相比我们自己实现代码也更加健壮。
跨平台路径分隔符
我们知道Windows和Linux的文件系统路径分隔符是不同的,如果混用可能导致一些错误。Go语言提供了os.PathSeparator作为跨平台的路径分隔符。我们对文件路径字符串进行处理时,应该使用该值,而非直接使用正斜杠或反斜杠。
package main
import (
"fmt"
"os"
)
func main() {
s := os.PathSeparator
fmt.Println(string(s))
}
这里os.PathSeparator实际上是一个rune类型(即int32),这里我们将其转换为了string类型进行输出。在Windows下,上面代码会输出反斜杠\。
获取文件路径和文件名
Dir()方法会解析一个文件路径字符串,返回其所在的目录;Base()方法则会返回文件名。
package main
import (
"fmt"
"path/filepath"
)
func main() {
dir := filepath.Dir("D:\\workspace-go\\filedemo\\data.txt")
base := filepath.Base("D:\\workspace-go\\filedemo\\data.txt")
fmt.Println(dir)
fmt.Println(base)
}
运行结果:
D:\workspace-go\filedemo
data.txt
如果指定路径最后带有路径分隔符,它会被视为文件夹进行处理。Dir()和Base()对文件的路径和文件夹的路径处理不同,举例来说,如果上面字符串s的值为D:\\workspace-go\\filedemo\\,输出结果为:
D:\workspace-go\filedemo
filedemo
计算绝对路径
IsAbs()方法用于判断一个路径是否为绝对路径,其内部逻辑很简单,/开头的路径就是Linux下的绝对路径,盘符开头的路径如c:/就是Windows下的绝对路径。Abs()方法用于计算一个路径的绝对路径,注意这个方法是根据当前Go程序的工作目录来计算的。
package main
import (
"fmt"
"path/filepath"
)
func main() {
s := "data.txt"
// 判断是否为绝对路径
result := filepath.IsAbs(s)
fmt.Printf("路径是否为绝对路径 %v\n", result)
// 获取一个路径的绝对路径
absPath, err := filepath.Abs(s)
if err != nil {
fmt.Println(err)
return
}
fmt.Printf("绝对路径 %v\n", absPath)
}
运行结果:
路径是否为绝对路径 false
绝对路径 D:\workspace-go\filedemo\data.txt
注:这里我的程序所在目录为D:\workspace-go\filedemo\。
计算相对路径
Rel()方法用于计算一个路径相对于另一个路径的相对路径值,其计算结果可能带有目录回退符..,这么说可能有点难理解,我们直接看一个例子。
package main
import (
"fmt"
"path/filepath"
)
func main() {
s1, err := filepath.Rel("E:\\", "E:\\workspace\\data.txt")
if err != nil {
fmt.Println(err)
return
}
fmt.Println(s1)
s2, err := filepath.Rel("E:\\demo", "E:\\workspace\\data.txt")
if err != nil {
fmt.Println(err)
return
}
fmt.Println(s2)
}
运行结果:
workspace\data.txt
..\workspace\data.txt
路径切分
Split()方法用于处理路径切分,其返回值是dir和file,对应文件所在路径值和文件名。
package main
import (
"fmt"
"path/filepath"
)
func main() {
var dir, file string
dir, file = filepath.Split("E:\\workspace-go\\data.txt")
fmt.Printf("dir [%v] file[%v]\n", dir, file)
dir, file = filepath.Split("data.txt")
fmt.Printf("dir [%v] file[%v]\n", dir, file)
dir, file = filepath.Split("E:\\workspace-go\\")
fmt.Printf("dir [%v] file[%v]\n", dir, file)
}
运行输出:
dir [E:\workspace-go\] file[data.txt]
dir [] file[data.txt]
dir [E:\workspace-go\] file[]
注意:和Dir()与Base()方法类似,Split()方法对文件夹和文件的处理是有区别的,而判断目录或是文件的依据是字符串结尾的分隔符。
路径拼接
Join()方法用于拼接路径,下面是一个例子。
package main
import (
"fmt"
"path/filepath"
)
func main() {
s := filepath.Join("E:\\", "workspace-go", "data.txt")
fmt.Println(s)
}
运行结果:
E:\workspace-go\data.txt
遍历目录
Walk()方法能够以递归形式遍历目录下的所有文件和文件夹。
package main
import (
"fmt"
"io/fs"
"path/filepath"
)
func main() {
if err := filepath.Walk("E:\\", func(path string, info fs.FileInfo, err error) error {
fmt.Println(path)
return err
}); err != nil {
fmt.Println(err)
return
}
}
运行上面代码后,会输出整个E盘下的所有文件和文件夹信息。