SDL3_API分类参考_文件系统(CategoryFilesystem)

2026-3-6 / 0 评论 / 6 阅读

文件系统子系统(CategoryFilesystem)

SDL 提供一套用于检查和操作系统文件系统的 API,涵盖了目录相关的大部分常用操作(实际的文件读写 I/O 功能由 CategoryIOStreamCategoryAsyncIO 模块提供)。

该模块可回答各类路径相关的核心问题:

  • 应用程序的数据目录在哪里?SDL_GetBasePath()
  • 哪里可以安全地写入文件?SDL_GetPrefPath()
  • 系统预设文件夹(下载、桌面、音乐等)的路径是什么?SDL_GetUserFolder()
  • 指定路径对应的文件/目录属性是什么?SDL_GetPathInfo()
  • 某个文件夹下包含哪些文件/子目录?SDL_EnumerateDirectory()
  • 按通配符匹配某个文件夹下的文件?SDL_GlobDirectory()
  • 当前工作目录是什么?SDL_GetCurrentDirectory()

此外,SDL 还提供了操作目录树的函数,支持文件/目录的重命名、删除、复制等操作。


函数

  • SDL_CopyFile:复制文件(支持跨目录复制,保留文件属性)
  • SDL_CreateDirectory:创建目录(支持创建单层目录,失败时返回具体错误)
  • SDL_EnumerateDirectory:枚举目录下的所有项(文件/子目录),通过回调函数处理每个项
  • SDL_GetBasePath:获取应用程序的基础目录(二进制文件所在目录,末尾带路径分隔符)
  • SDL_GetCurrentDirectory:获取当前工作目录(进程的当前工作路径)
  • SDL_GetPathInfo:获取指定路径的详细信息(类型、大小、修改时间等,存储在 SDL_PathInfo 中)
  • SDL_GetPrefPath:获取应用程序的偏好设置目录(可安全写入的目录,按厂商/应用名划分)
  • SDL_GetUserFolder:获取系统预设的用户文件夹路径(桌面、下载、音乐等)
  • SDL_GlobDirectory:按通配符匹配枚举目录下的文件(支持 *、? 等通配符)
  • SDL_RemovePath:删除指定路径(文件/空目录,非空目录删除失败)
  • SDL_RenamePath:重命名/移动文件/目录(支持跨目录移动,目标路径已存在则失败)

数据类型

  • SDL_EnumerateDirectoryCallback:目录枚举回调函数类型(处理每个枚举到的文件/目录项)
  • SDL_GlobFlags:通配符枚举标志类型(控制 Glob 匹配的行为,如大小写敏感、递归等)

结构体

  • SDL_PathInfo:路径信息结构体(包含路径类型、大小、创建时间、修改时间等属性)

枚举

  • SDL_EnumerationResult:目录枚举结果枚举(控制是否继续枚举,如继续、停止、跳过当前项)
  • SDL_Folder:系统预设文件夹类型枚举(桌面、下载、音乐、文档、图片等)
  • SDL_PathType:路径类型枚举(文件、目录、符号链接、不存在等)

FreeBASIC 示例代码

' 引入 SDL 相关声明(需确保 FreeBASIC 已链接 SDL3 库)
#Include "SDL.bi"

' 补充枚举定义
Enum SDL_PathType
    SDL_PATH_TYPE_NONE = 0        ' 路径不存在
    SDL_PATH_TYPE_FILE = 1        ' 普通文件
    SDL_PATH_TYPE_DIRECTORY = 2   ' 目录
    SDL_PATH_TYPE_SYMLINK = 3     ' 符号链接
    SDL_PATH_TYPE_OTHER = 4       ' 其他类型
End Enum

Enum SDL_Folder
    SDL_FOLDER_DESKTOP = 0        ' 桌面
    SDL_FOLDER_DOWNLOADS = 1      ' 下载
    SDL_FOLDER_DOCUMENTS = 2      ' 文档
    SDL_FOLDER_MUSIC = 3          ' 音乐
    SDL_FOLDER_PICTURES = 4       ' 图片
    SDL_FOLDER_VIDEOS = 5         ' 视频
    SDL_FOLDER_APPDATA = 6        ' 应用数据
End Enum

Enum SDL_EnumerationResult
    SDL_ENUMERATION_CONTINUE = 0  ' 继续枚举
    SDL_ENUMERATION_STOP = 1      ' 停止枚举
    SDL_ENUMERATION_SKIP = 2      ' 跳过当前项
End Enum

' 补充结构体定义
Type SDL_PathInfo
    type_ As SDL_PathType         ' 路径类型
    size As ULLong                ' 文件大小(字节),目录为0
    created As SDL_Time           ' 创建时间(纳秒时间戳)
    modified As SDL_Time          ' 修改时间(纳秒时间戳)
    accessed As SDL_Time          ' 访问时间(纳秒时间戳)
End Type

' 补充函数指针类型定义
Type SDL_EnumerateDirectoryCallback As Function CDecl (ByVal path As ZString Ptr, ByVal info As SDL_PathInfo Ptr, ByVal userdata As Any Ptr) As SDL_EnumerationResult

' 补充函数声明(FreeBASIC 绑定可能缺失)
Declare Function SDL_GetBasePath CDecl () As ZString Ptr
Declare Function SDL_GetPrefPath CDecl (ByVal org As ZString Ptr, ByVal app As ZString Ptr) As ZString Ptr
Declare Function SDL_GetUserFolder CDecl (ByVal folder As SDL_Folder) As ZString Ptr
Declare Function SDL_GetCurrentDirectory CDecl () As ZString Ptr
Declare Function SDL_GetPathInfo CDecl (ByVal path As ZString Ptr, ByVal info As SDL_PathInfo Ptr) As Integer
Declare Function SDL_EnumerateDirectory CDecl (ByVal dir As ZString Ptr, ByVal callback As SDL_EnumerateDirectoryCallback, ByVal userdata As Any Ptr) As Integer
Declare Function SDL_CreateDirectory CDecl (ByVal path As ZString Ptr) As Integer
Declare Function SDL_CopyFile CDecl (ByVal src As ZString Ptr, ByVal dst As ZString Ptr) As Integer
Declare Function SDL_RenamePath CDecl (ByVal oldpath As ZString Ptr, ByVal newpath As ZString Ptr) As Integer
Declare Function SDL_RemovePath CDecl (ByVal path As ZString Ptr) As Integer

' 目录枚举回调函数:打印每个文件/目录信息
Function EnumDirCallback CDecl (ByVal path As ZString Ptr, ByVal info As SDL_PathInfo Ptr, ByVal userdata As Any Ptr) As SDL_EnumerationResult
    Dim As ZString * 20 typeStr
    Select Case info->type_
        Case SDL_PATH_TYPE_FILE: typeStr = "文件"
        Case SDL_PATH_TYPE_DIRECTORY: typeStr = "目录"
        Case SDL_PATH_TYPE_SYMLINK: typeStr = "符号链接"
        Case Else: typeStr = "其他类型"
    End Select

    SDL_LogInfo(SDL_LOG_CATEGORY_FILESYSTEM, "  %s - [%s] 大小:%llu 字节", *path, typeStr, info->size)

    ' 继续枚举所有项
    Return SDL_ENUMERATION_CONTINUE
End Function

' 打印路径信息
Sub PrintPathInfo(ByVal path As ZString Ptr, ByVal title As ZString Ptr)
    SDL_LogInfo(SDL_LOG_CATEGORY_FILESYSTEM, "=== %s ===", title)

    Dim As SDL_PathInfo info
    If (SDL_GetPathInfo(path, @info) = 0) Then
        Dim As ZString * 20 typeStr
        Select Case info.type_
            Case SDL_PATH_TYPE_NONE: typeStr = "不存在"
            Case SDL_PATH_TYPE_FILE: typeStr = "普通文件"
            Case SDL_PATH_TYPE_DIRECTORY: typeStr = "目录"
            Case SDL_PATH_TYPE_SYMLINK: typeStr = "符号链接"
            Case SDL_PATH_TYPE_OTHER: typeStr = "其他类型"
        End Select

        SDL_LogInfo(SDL_LOG_CATEGORY_FILESYSTEM, "  路径:%s", *path)
        SDL_LogInfo(SDL_LOG_CATEGORY_FILESYSTEM, "  类型:%s", typeStr)
        SDL_LogInfo(SDL_LOG_CATEGORY_FILESYSTEM, "  大小:%llu 字节", info.size)
        SDL_LogInfo(SDL_LOG_CATEGORY_FILESYSTEM, "  创建时间:%llu ns", info.created)
        SDL_LogInfo(SDL_LOG_CATEGORY_FILESYSTEM, "  修改时间:%llu ns", info.modified)
    Else
        SDL_LogError(SDL_LOG_CATEGORY_FILESYSTEM, "获取路径信息失败:%s", SDL_GetError())
    End If
End Sub

' 主程序
Sub Main()
    ' 初始化 SDL(Filesystem 模块无需显式初始化子系统)
    If (SDL_Init(0) < 0) Then
        SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "SDL 初始化失败:%s", SDL_GetError())
        Exit Sub
    End If

    ' ========== 1. 获取系统/应用路径 ==========
    SDL_LogInfo(SDL_LOG_CATEGORY_FILESYSTEM, "【1. 获取系统/应用路径】")

    ' 应用基础目录
    Dim As ZString Ptr basePath = SDL_GetBasePath()
    If (basePath <> NULL) Then
        SDL_LogInfo(SDL_LOG_CATEGORY_FILESYSTEM, "应用基础目录:%s", *basePath)
        SDL_free(basePath) ' 必须释放 SDL 分配的字符串
    End If

    ' 应用偏好设置目录(厂商名/应用名)
    Dim As ZString Ptr prefPath = SDL_GetPrefPath("SDL_Example", "FilesystemDemo")
    If (prefPath <> NULL) Then
        SDL_LogInfo(SDL_LOG_CATEGORY_FILESYSTEM, "应用偏好设置目录:%s", *prefPath)
    End If

    ' 当前工作目录
    Dim As ZString Ptr cwd = SDL_GetCurrentDirectory()
    If (cwd <> NULL) Then
        SDL_LogInfo(SDL_LOG_CATEGORY_FILESYSTEM, "当前工作目录:%s", *cwd)
        SDL_free(cwd)
    End If

    ' 系统预设用户文件夹
    Dim As ZString * 20 folderNames(0 To 5) = {
        "桌面", "下载", "文档", "音乐", "图片", "视频"
    }
    For i As Integer = 0 To 5
        Dim As ZString Ptr folderPath = SDL_GetUserFolder(i)
        If (folderPath <> NULL) Then
            SDL_LogInfo(SDL_LOG_CATEGORY_FILESYSTEM, "%s 目录:%s", folderNames(i), *folderPath)
            SDL_free(folderPath)
        End If
    Next

    ' ========== 2. 创建测试目录和文件 ==========
    SDL_LogInfo(SDL_LOG_CATEGORY_FILESYSTEM, vbCrLf & "【2. 创建测试目录和文件】")

    ' 拼接测试目录路径(偏好设置目录下的 test_dir)
    Dim As String testDirPath = *prefPath & "test_dir"
    If (SDL_CreateDirectory(StrPtr(testDirPath)) = 0) Then
        SDL_LogInfo(SDL_LOG_CATEGORY_FILESYSTEM, "创建测试目录成功:%s", testDirPath)
    Else
        SDL_LogError(SDL_LOG_CATEGORY_FILESYSTEM, "创建测试目录失败:%s", SDL_GetError())
    End If

    ' 创建测试文件(FreeBASIC 原生文件操作)
    Dim As String testFilePath = testDirPath & "/test.txt"
    Dim As Integer fileHandle = FreeFile()
    If (Open(testFilePath For Output As #fileHandle) = 0) Then
        Print #fileHandle, "SDL Filesystem 测试文件"
        Close #fileHandle
        SDL_LogInfo(SDL_LOG_CATEGORY_FILESYSTEM, "创建测试文件成功:%s", testFilePath)
    End If

    ' ========== 3. 获取路径信息 ==========
    SDL_LogInfo(SDL_LOG_CATEGORY_FILESYSTEM, vbCrLf & "【3. 获取路径信息】")
    PrintPathInfo(StrPtr(testFilePath), "测试文件信息")
    PrintPathInfo(StrPtr(testDirPath), "测试目录信息")

    ' ========== 4. 枚举目录内容 ==========
    SDL_LogInfo(SDL_LOG_CATEGORY_FILESYSTEM, vbCrLf & "【4. 枚举测试目录内容】")
    If (SDL_EnumerateDirectory(StrPtr(testDirPath), @EnumDirCallback, NULL) = 0) Then
        SDL_LogInfo(SDL_LOG_CATEGORY_FILESYSTEM, "目录枚举完成")
    Else
        SDL_LogError(SDL_LOG_CATEGORY_FILESYSTEM, "目录枚举失败:%s", SDL_GetError())
    End If

    ' ========== 5. 复制/重命名/删除文件 ==========
    SDL_LogInfo(SDL_LOG_CATEGORY_FILESYSTEM, vbCrLf & "【5. 文件操作:复制/重命名/删除】")

    ' 复制文件
    Dim As String copyFilePath = testDirPath & "/test_copy.txt"
    If (SDL_CopyFile(StrPtr(testFilePath), StrPtr(copyFilePath)) = 0) Then
        SDL_LogInfo(SDL_LOG_CATEGORY_FILESYSTEM, "复制文件成功:%s -> %s", testFilePath, copyFilePath)
    Else
        SDL_LogError(SDL_LOG_CATEGORY_FILESYSTEM, "复制文件失败:%s", SDL_GetError())
    End If

    ' 重命名文件
    Dim As String renameFilePath = testDirPath & "/test_renamed.txt"
    If (SDL_RenamePath(StrPtr(copyFilePath), StrPtr(renameFilePath)) = 0) Then
        SDL_LogInfo(SDL_LOG_CATEGORY_FILESYSTEM, "重命名文件成功:%s -> %s", copyFilePath, renameFilePath)
    Else
        SDL_LogError(SDL_LOG_CATEGORY_FILESYSTEM, "重命名文件失败:%s", SDL_GetError())
    End If

    ' 删除文件
    If (SDL_RemovePath(StrPtr(testFilePath)) = 0) Then
        SDL_LogInfo(SDL_LOG_CATEGORY_FILESYSTEM, "删除文件成功:%s", testFilePath)
    End If
    If (SDL_RemovePath(StrPtr(renameFilePath)) = 0) Then
        SDL_LogInfo(SDL_LOG_CATEGORY_FILESYSTEM, "删除文件成功:%s", renameFilePath)
    End If

    ' 删除目录(必须为空)
    If (SDL_RemovePath(StrPtr(testDirPath)) = 0) Then
        SDL_LogInfo(SDL_LOG_CATEGORY_FILESYSTEM, "删除测试目录成功:%s", testDirPath)
    Else
        SDL_LogError(SDL_LOG_CATEGORY_FILESYSTEM, "删除测试目录失败(可能非空):%s", SDL_GetError())
    End If

    ' 释放内存
    If (prefPath <> NULL) Then
        SDL_free(prefPath)
    End If

    ' 清理 SDL
    SDL_Quit()

    SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, vbCrLf & "程序正常退出")
End Sub

' 运行主程序
Main()

核心知识点补充

  1. 路径管理核心规则

    • SDL_GetBasePath() 返回的路径末尾自带路径分隔符(/ 或 \),拼接子路径时无需额外添加;
    • SDL_GetPrefPath() 需要传入厂商名和应用名,返回的目录是系统推荐的可写入目录(跨平台兼容);
    • SDL 分配的路径字符串(如 SDL_GetBasePath() 返回值)必须用 SDL_free() 释放,避免内存泄漏。
  2. 路径类型与操作限制

    • SDL_RemovePath() 只能删除文件或空目录,非空目录需先删除内部文件;
    • SDL_CreateDirectory() 仅创建单层目录,创建多级目录需逐层调用;
    • SDL_RenamePath() 支持跨目录移动文件,但目标路径不能已存在。
  3. 目录枚举回调函数

    • 返回 SDL_ENUMERATION_CONTINUE:继续枚举下一个项;
    • 返回 SDL_ENUMERATION_STOP:立即停止枚举;
    • 返回 SDL_ENUMERATION_SKIP:跳过当前项,继续枚举下一个;
    • 回调函数中可通过 SDL_PathInfo 判断项的类型(文件/目录),实现差异化处理。
  4. 系统预设文件夹兼容性

    • SDL_GetUserFolder() 返回的路径因操作系统而异:
      • Windows:C:\Users\<用户名>\Desktop/Downloads 等;
      • macOS:/Users/<用户名>/Desktop/Downloads 等;
      • Linux:/home/<用户名>/Desktop/Downloads 等;
    • 部分平台可能不支持某些文件夹类型,返回 NULL,需做空指针判断。

总结

  1. 核心优势

    • 提供跨平台统一的文件系统操作接口,屏蔽不同系统的路径格式、目录结构差异;
    • 自动适配系统的可写入目录、用户预设文件夹,避免手动拼接路径导致的兼容性问题;
    • 内置路径信息查询、目录枚举、文件操作等完整功能,无需依赖平台原生 API;
    • 内存管理清晰,SDL 分配的字符串需用 SDL_free() 释放,符合 SDL 内存管理规范。
  2. 使用建议

    • 优先使用 SDL_GetPrefPath() 存储应用配置文件,而非自定义路径,确保跨平台可写入;
    • 枚举目录时通过回调函数处理每个项,避免一次性加载大量文件导致内存占用过高;
    • 所有文件/目录操作后检查返回值,失败时通过 SDL_GetError() 获取具体错误信息;
    • 拼接路径时注意路径分隔符,优先使用 SDL 返回的带分隔符路径,避免手动拼接出错。
  3. 关键接口

    • 路径获取:SDL_GetBasePath()/SDL_GetPrefPath()/SDL_GetUserFolder()/SDL_GetCurrentDirectory()
    • 路径信息:SDL_GetPathInfo()
    • 目录操作:SDL_CreateDirectory()/SDL_EnumerateDirectory()
    • 文件操作:SDL_CopyFile()/SDL_RenamePath()/SDL_RemovePath()

评论一下?

OωO
取消