2023-03-27:avio_list_dir.c 是 FFmpeg 库自带的一个示例程序,它提供了列出目录中

2023-03-27:avio_list_dir.c 是 FFmpeg 库自带的一个示例程序,它提供了列出目录中所有文件和子目录的功能,请用go语言改写。

答案2023-03-27:

这段代码实现了通过 AVIOContext 列出指定目录下的文件和子目录,并打印出它们的名称、大小、类型、权限等信息。

具体流程如下:

1.设置 FFmpeg 库的路径,以及调用 AvformatNetworkInit() 初始化网络相关的组件。

2.调用 AvioOpenDir() 打开指定目录,获取 AVIODirContext 对象。

3.循环调用 AVIODirContext.AvioReadDir() 方法读取目录下的文件和子目录,每次读取到一个目录项后,输出该目录项的信息。如果已经读取完所有目录项,则退出循环。

4.输出格式化的目录项信息,包括类型、大小、名称、权限等。

5.在每次循环中需要调用 AVIODirContext.AvioFreeDirectoryEntry() 方法释放当前目录项所占用的内存空间。

6.最后调用 AvioCloseDir() 关闭目录并销毁 AVIODirContext 对象,调用 AvformatNetworkDeinit() 释放网络相关的资源。

需要注意的是,这段代码只能在支持 AVIOContext 的平台上运行,例如 Linux 上的文件系统或者 S3、HDFS 等云存储服务。而 Windows 平台上不支持 AVIOContext,因此无法使用该方法列出目录下的文件和子目录。

代码见github/moonfdd/ffmpeg-go。

执行命令:

go run ./examples/internalexamples/avio_list_dir/main.go .

golang代码如下:

package main

import (
    "fmt"
    "os"

    "github.com/moonfdd/ffmpeg-go/ffcommon"
    "github.com/moonfdd/ffmpeg-go/libavformat"
    "github.com/moonfdd/ffmpeg-go/libavutil"
)

func main() {

    os.Setenv("Path", os.Getenv("Path")+";./lib")
    ffcommon.SetAvutilPath("./lib/avutil-56.dll")
    ffcommon.SetAvcodecPath("./lib/avcodec-58.dll")
    ffcommon.SetAvdevicePath("./lib/avdevice-58.dll")
    ffcommon.SetAvfilterPath("./lib/avfilter-56.dll")
    ffcommon.SetAvformatPath("./lib/avformat-58.dll")
    ffcommon.SetAvpostprocPath("./lib/postproc-55.dll")
    ffcommon.SetAvswresamplePath("./lib/swresample-3.dll")
    ffcommon.SetAvswscalePath("./lib/swscale-5.dll")

    genDir := "./out"
    _, err := os.Stat(genDir)
    if err != nil {
        if os.IsNotExist(err) {
            os.Mkdir(genDir, 0777) //  Everyone can read write and execute
        }
    }
    main0()
}
func main0() (ret ffcommon.FInt) {

    libavutil.AvLogSetLevel(libavutil.AV_LOG_DEBUG)

    if len(os.Args) < 2 {
        usage(os.Args[0])
        ret = 1
        return
    }

    libavformat.AvformatNetworkInit()

    ret = list_op(os.Args[1])

    libavformat.AvformatNetworkDeinit()

    if ret < 0 {
        ret = 1
    }
    return
}

func type_string(type0 int32) string {
    switch type0 {
    case libavformat.AVIO_ENTRY_DIRECTORY:
        return "<DIR>"
    case libavformat.AVIO_ENTRY_FILE:
        return "<FILE>"
    case libavformat.AVIO_ENTRY_BLOCK_DEVICE:
        return "<BLOCK DEVICE>"
    case libavformat.AVIO_ENTRY_CHARACTER_DEVICE:
        return "<CHARACTER DEVICE>"
    case libavformat.AVIO_ENTRY_NAMED_PIPE:
        return "<PIPE>"
    case libavformat.AVIO_ENTRY_SYMBOLIC_LINK:
        return "<LINK>"
    case libavformat.AVIO_ENTRY_SOCKET:
        return "<SOCKET>"
    case libavformat.AVIO_ENTRY_SERVER:
        return "<SERVER>"
    case libavformat.AVIO_ENTRY_SHARE:
        return "<SHARE>"
    case libavformat.AVIO_ENTRY_WORKGROUP:
        return "<WORKGROUP>"
    case libavformat.AVIO_ENTRY_UNKNOWN:
    default:
        break
    }
    return "<UNKNOWN>"
}

func list_op(input_dir string) (ret int32) {
    var entry *libavformat.AVIODirEntry
    var ctx *libavformat.AVIODirContext
    var cnt int32
    var filemode [4]byte
    var uid_and_gid [20]byte

    //注意Windows下会返回-40,也就是Function not implement,方法未实现,也就是说windows下不支持此方法
    ret = libavformat.AvioOpenDir(&ctx, input_dir, nil)
    defer libavformat.AvioCloseDir(&ctx)

    if ret < 0 {
        libavutil.AvLog(uintptr(0), libavutil.AV_LOG_ERROR, "Cannot open directory: %s.\n", libavutil.AvErr2str(ret))
        return
    }

    cnt = 0
    for {
        ret = ctx.AvioReadDir(&entry)
        if ret < 0 {
            libavutil.AvLog(uintptr(0), libavutil.AV_LOG_ERROR, "Cannot list directory: %s.\n", libavutil.AvErr2str(ret))
            return
        }
        if entry == nil {
            break
        }
        if entry.Filemode == -1 {
            filemode[0] = '?'
            filemode[1] = '?'
            filemode[2] = '?'
        } else {
            f := fmt.Sprint(entry.Filemode)
            if len(f) >= 1 {
                filemode[0] = f[0]
            }
            if len(f) >= 2 {
                filemode[1] = f[1]
            }
            if len(f) >= 3 {
                filemode[2] = f[2]
            }
        }
        u := fmt.Sprintf("%d%d", entry.UserId, entry.GroupId)
        copy(uid_and_gid[0:19], []byte(u))

        if cnt == 0 {
            libavutil.AvLog(uintptr(0), libavutil.AV_LOG_INFO, "%-9s %12s %30s %10s %s %16s %16s %16s\n",
                "TYPE", "SIZE", "NAME", "UID(GID)", "UGO", "MODIFIED",
                "ACCESSED", "STATUS_CHANGED")
        }
        libavutil.AvLog(uintptr(0), libavutil.AV_LOG_INFO, "%-9s %12s %30s %10s %s %16s %16s %16s\n",
            type_string(entry.Type),
            fmt.Sprint(entry.Size),
            ffcommon.StringFromPtr(entry.Name),
            string(uid_and_gid[:]),
            fmt.Sprint(filemode),
            fmt.Sprint(entry.ModificationTimestamp),
            fmt.Sprint(entry.AccessTimestamp),
            fmt.Sprint(entry.StatusChangeTimestamp))
        libavformat.AvioFreeDirectoryEntry(&entry)
        cnt++
    }
    return
}

func usage(program_name string) {
    fmt.Printf("usage: %s input_dir\nAPI example program to show how to list files in directory accessed through AVIOContext.\n", program_name)
}

在这里插入图片描述

本作品采用《CC 协议》,转载必须注明作者和本文链接
微信公众号:福大大架构师每日一题。最新面试题,涉及golang,rust,mysql,redis,云原生,算法,分布式,网络,操作系统。
讨论数量: 0
(= ̄ω ̄=)··· 暂无内容!

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!
未填写
文章
486
粉丝
23
喜欢
38
收藏
22
排名:452
访问:2.0 万
私信
所有博文
社区赞助商