Golang中os.File如何实现FileInfo()方法
Golang中os.File如何实现FileInfo()方法 你好,
我在搜索如何使用Go解压文件并尝试理解代码时,在这个步骤卡住了:f.FileInfo()。
os.File 的 FileInfo() 函数实现在哪里?
我在GitHub上的Go代码库中搜索但没有找到,有人能帮忙指出具体位置吗?
以下是我作为参考的代码(来自 https://golangcode.com/unzip-files-in-go/)
package main
import (
"archive/zip"
"fmt"
"io"
"log"
"os"
"path/filepath"
"strings"
)
func main() {
files, err := Unzip("done.zip", "output-folder")
if err != nil {
log.Fatal(err)
}
fmt.Println("Unzipped:\n" + strings.Join(files, "\n"))
}
// Unzip will decompress a zip archive, moving all files and folders
// within the zip file (parameter 1) to an output directory (parameter 2).
func Unzip(src string, dest string) ([]string, error) {
var filenames []string
r, err := zip.OpenReader(src)
if err != nil {
return filenames, err
}
defer r.Close()
for _, f := range r.File {
// Store filename/path for returning and using later on
fpath := filepath.Join(dest, f.Name)
// Check for ZipSlip. More Info: http://bit.ly/2MsjAWE
if !strings.HasPrefix(fpath, filepath.Clean(dest)+string(os.PathSeparator)) {
return filenames, fmt.Errorf("%s: illegal file path", fpath)
}
filenames = append(filenames, fpath)
if f.FileInfo().IsDir() {
// Make Folder
os.MkdirAll(fpath, os.ModePerm)
continue
}
// Make File
if err = os.MkdirAll(filepath.Dir(fpath), os.ModePerm); err != nil {
return filenames, err
}
outFile, err := os.OpenFile(fpath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, f.Mode())
if err != nil {
return filenames, err
}
rc, err := f.Open()
if err != nil {
return filenames, err
}
_, err = io.Copy(outFile, rc)
// Close the file without defer to close before next iteration of loop
outFile.Close()
rc.Close()
if err != nil {
return filenames, err
}
}
return filenames, nil
}
更多关于Golang中os.File如何实现FileInfo()方法的实战教程也可以访问 https://www.itying.com/category-94-b0.html
这类似于
zip
FileHeader
FileInfoHeader
FileHeader
FileInfo
更多关于Golang中os.File如何实现FileInfo()方法的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
FileInfo 是一个接口
type FileInfo interface {
Name() string // 文件的基本名称
Size() int64 // 常规文件的字节长度;其他文件类型取决于系统
Mode() FileMode // 文件模式位
ModTime() time.Time // 修改时间
IsDir() bool // Mode().IsDir() 的简写形式
Sys() interface{} // 底层数据源(可能返回 nil)
}
哦抱歉,我误解了文档,我以为结构体Reader(由archive/zip中的ReadCloser实现)使用的是os.File,但实际上它使用的是archive/zip中的File(正如建议的那样,它实现了FileHeader)
type Reader struct {
r io.ReaderAt
File []*File
Comment string
decompressors map[uint16]Decompressor
}
type ReadCloser struct {
f *os.File
Reader
}
type File struct {
FileHeader
zip *Reader
zipr io.ReaderAt
zipsize int64
headerOffset int64
}
谢谢!
在您提供的代码中,f.FileInfo() 方法调用的是 zip.File 类型的 FileInfo() 方法,而不是 os.File 的方法。让我详细解释一下:
zip.File 的 FileInfo() 方法
zip.File 类型确实有一个 FileInfo() 方法,它返回一个 os.FileInfo 接口。这个方法在 Go 标准库的 archive/zip 包中实现。
源码位置
在 Go 源码中,zip.File 的 FileInfo() 方法实现位于:
src/archive/zip/struct.go
实现原理
zip.File 结构体内部存储了文件的元数据信息,FileInfo() 方法会基于这些信息创建一个 fileInfo 结构体实例,该结构体实现了 os.FileInfo 接口的所有方法。
示例代码演示
package main
import (
"archive/zip"
"fmt"
"log"
"time"
)
func main() {
// 打开 zip 文件
r, err := zip.OpenReader("example.zip")
if err != nil {
log.Fatal(err)
}
defer r.Close()
// 遍历 zip 中的文件
for _, f := range r.File {
// 调用 FileInfo() 方法获取文件信息
fileInfo := f.FileInfo()
fmt.Printf("文件名: %s\n", fileInfo.Name())
fmt.Printf("文件大小: %d bytes\n", fileInfo.Size())
fmt.Printf("是否是目录: %t\n", fileInfo.IsDir())
fmt.Printf("修改时间: %s\n", fileInfo.ModTime().Format(time.RFC3339))
fmt.Printf("权限模式: %s\n", fileInfo.Mode())
fmt.Printf("系统信息: %v\n", fileInfo.Sys())
fmt.Println("---")
}
}
底层实现简化版
zip.File 的 FileInfo() 方法大致是这样实现的:
// 在 archive/zip 包中的实现
func (f *File) FileInfo() os.FileInfo {
return &fileInfo{
name: f.Name,
size: int64(f.UncompressedSize64),
mode: f.Mode(),
modTime: f.ModTime(),
}
}
// fileInfo 结构体实现 os.FileInfo 接口
type fileInfo struct {
name string
size int64
mode os.FileMode
modTime time.Time
}
func (fi *fileInfo) Name() string { return fi.name }
func (fi *fileInfo) Size() int64 { return fi.size }
func (fi *fileInfo) Mode() os.FileMode { return fi.mode }
func (fi *fileInfo) ModTime() time.Time { return fi.modTime }
func (fi *fileInfo) IsDir() bool { return fi.mode.IsDir() }
func (fi *fileInfo) Sys() interface{} { return nil }
在您的解压代码中,f.FileInfo().IsDir() 就是通过这种方式判断 zip 条目是否为目录的。


