Go语言 使用新的io.FS到fs.walkDir &跨文件系统类型列出文件

voase2hg  于 2023-11-14  发布在  Go
关注(0)|答案(1)|浏览(105)

我使用新的io.FS抽象来遍历文件系统,并读取每个文件的前128个字节,这些字节与我们内部的文件扩展名相匹配。
这些文件位于本地文件系统和归档文件等(ZIP和Tar I thunk)中。
我正在使用fs.WalkDir,传入一个fs.FS(在我的测试中是os. dll和fstest.MapFS)。当遍历时,我返回一个“文件”数组(实际上它们是 *.pzix和 *.pzi文件,这是我们的专用格式)。我找不到一个合适的方法来使用FS接口来获取我正在处理的文件的一些信息。
我想:

  • 获取文件名
  • 获取文件大小
  • 获取openfile方法

我发现Go中的接口有点混乱,来自Java/C#。我希望在抽象上操作,但我不知道如何获得文件本身的其他实现(例如,文件接口有Stat()和read)。
我发现的最简单的方法是将路径和文件名存储在数组中,然后当我遍历数组时,确定它是os.Dir还是fstest.MapFS,但这似乎是违反直觉的:

func collectFiles(f fs.FS, root string) []string {
 var files []string
 fs.WalkDir(f, ".", func(p string, d fs.DirEntry, err error) error {
  if !d.IsDir() { // we also check a few other things in the filename here
   f = filepath.Abs(path.Join(root, p))
   files = append(files, f)
  }
 }
 return files
}

字符串
这给了我:

root = "m://" // mapfs
files = { "m://id-198271.pzi", "m://id-7125-092581.pzix"}


有没有更聪明的方法来处理抽象而不做这些事情呢?因为在数组返回后,我必须“打开"文件,读取前128个字节(签名)并对文件的其余部分进行散列以确保其”有效“。
编辑:为了澄清,collectFiles方法正在创建我们的主要文件命中列表,以便在另一个方法中工作。我希望将本地系统文件,zip文件和tar文件传入该方法,以便它可以遍历归档文件中的文件并将它们添加到数组中。
我希望有一个类似File的接口,可以存储在数组中,而不是一个字符串,这样后续的调用者就可以在不知道底层内容的情况下执行f.open()。

fnatzsnv

fnatzsnv1#

获取文件名
p是文件系统中的名称。
获取文件大小
通过调用fs.Stat(f, p)获取大小
获取openfile方法
使用f.Open(p)打开文件
范例:

f := os.DirFS("/etc")
fs.WalkDir(f, ".", func(p string, d fs.DirEntry, err error) error {
    if !d.IsDir() {
        st, _ := fs.Stat(f, p)
        r, _ := f.Open(p)
        defer r.Close()

        // Read prefix
        var buf [md5.Size]byte
        n, _ := io.ReadFull(r, buf[:])

        // Hash remainder
        h := md5.New()
        _, _ = io.Copy(h, r)
        s := h.Sum(nil)

        fmt.Printf("%s %d %x %x\n", p, st.Size(), buf[:n], s)
    }
    return nil
})

字符串
为了简洁起见,这个例子忽略了错误。不要在真实的代码中这样做。
https://go.dev/play/p/W7He_YNSZFU

相关问题