输入输出流子系统(CategoryIOStream)
SDL 提供了一套用于读写数据流的抽象接口,支持文件、内存等多种数据源的实现,同时应用程序也可以自定义实现该接口。
注意:SDL_IOStream 与 C++ 标准库中的 iostream 类无关联,仅二者都是用于读写数据的抽象接口这一点相似。
函数
- SDL_CloseIO:关闭 IO 流(释放相关资源,关闭底层数据源)
- SDL_FlushIO:刷新 IO 流(将缓冲区数据写入底层数据源,确保数据持久化)
- SDL_GetIOProperties:获取 IO 流的属性(如是否可读写、是否支持定位等)
- SDL_GetIOSize:获取 IO 流的总大小(字节),仅支持可定位的流
- SDL_GetIOStatus:获取 IO 流的当前状态(成功、EOF、错误等)
- SDL_IOFromConstMem:从只读内存块创建 IO 流(数据源为 const 内存,仅支持读操作)
- SDL_IOFromDynamicMem:从动态内存创建 IO 流(自动管理内存,支持读写,可扩容)
- SDL_IOFromFile:从文件创建 IO 流(指定文件路径和打开模式,如 "rb"、"wb" 等)
- SDL_IOFromMem:从内存块创建 IO 流(数据源为可读写内存,支持读写操作)
- SDL_IOprintf:格式化写入 IO 流(类似标准库 printf,输出到 IO 流)
- SDL_IOvprintf:可变参数格式化写入 IO 流(底层实现,通常不直接调用)
- SDL_LoadFile:加载整个文件到内存(自动分配内存,返回文件数据和大小)
- SDL_LoadFile_IO:从 IO 流加载全部数据到内存(自动分配内存,适配任意 IO 流)
- SDL_OpenIO:打开自定义 IO 流(基于 SDL_IOStreamInterface 实现自定义数据源)
- SDL_ReadIO:从 IO 流读取指定字节数的数据到缓冲区(返回实际读取的字节数)
- SDL_ReadS16BE:从 IO 流读取大端序 16 位有符号整数
- SDL_ReadS16LE:从 IO 流读取小端序 16 位有符号整数
- SDL_ReadS32BE:从 IO 流读取大端序 32 位有符号整数
- SDL_ReadS32LE:从 IO 流读取小端序 32 位有符号整数
- SDL_ReadS64BE:从 IO 流读取大端序 64 位有符号整数
- SDL_ReadS64LE:从 IO 流读取小端序 64 位有符号整数
- SDL_ReadS8:从 IO 流读取 8 位有符号整数(字节)
- SDL_ReadU16BE:从 IO 流读取大端序 16 位无符号整数
- SDL_ReadU16LE:从 IO 流读取小端序 16 位无符号整数
- SDL_ReadU32BE:从 IO 流读取大端序 32 位无符号整数
- SDL_ReadU32LE:从 IO 流读取小端序 32 位无符号整数
- SDL_ReadU64BE:从 IO 流读取大端序 64 位无符号整数
- SDL_ReadU64LE:从 IO 流读取小端序 64 位无符号整数
- SDL_ReadU8:从 IO 流读取 8 位无符号整数(字节)
- SDL_SaveFile:将内存数据保存到文件(指定路径和数据,自动创建/覆盖文件)
- SDL_SaveFile_IO:将内存数据保存到 IO 流(适配任意可写 IO 流)
- SDL_SeekIO:定位 IO 流的读写指针(支持相对当前位置、开头、末尾定位)
- SDL_TellIO:获取 IO 流当前读写指针位置(距离流开头的字节数)
- SDL_WriteIO:将缓冲区数据写入 IO 流(返回实际写入的字节数)
- SDL_WriteS16BE:向 IO 流写入大端序 16 位有符号整数
- SDL_WriteS16LE:向 IO 流写入小端序 16 位有符号整数
- SDL_WriteS32BE:向 IO 流写入大端序 32 位有符号整数
- SDL_WriteS32LE:向 IO 流写入小端序 32 位有符号整数
- SDL_WriteS64BE:向 IO 流写入大端序 64 位有符号整数
- SDL_WriteS64LE:向 IO 流写入小端序 64 位有符号整数
- SDL_WriteS8:向 IO 流写入 8 位有符号整数(字节)
- SDL_WriteU16BE:向 IO 流写入大端序 16 位无符号整数
- SDL_WriteU16LE:向 IO 流写入小端序 16 位无符号整数
- SDL_WriteU32BE:向 IO 流写入大端序 32 位无符号整数
- SDL_WriteU32LE:向 IO 流写入小端序 32 位无符号整数
- SDL_WriteU64BE:向 IO 流写入大端序 64 位无符号整数
- SDL_WriteU64LE:向 IO 流写入小端序 64 位无符号整数
- SDL_WriteU8:向 IO 流写入 8 位无符号整数(字节)
数据类型
- SDL_IOStream:IO 流句柄类型(标识一个打开的 IO 流,所有操作均基于此句柄)
结构体
- SDL_IOStreamInterface:IO 流接口结构体(自定义 IO 流时使用,包含读写、定位、关闭等函数指针)
枚举
- SDL_IOStatus:IO 流状态枚举(成功、到达文件末尾、读错误、写错误、定位错误等)
- SDL_IOWhence:IO 流定位基准枚举(SDL_IO_SEEK_SET:开头,SDL_IO_SEEK_CUR:当前位置,SDL_IO_SEEK_END:末尾)
宏
- (无)
FreeBASIC 示例代码
' 引入 SDL 相关声明(需确保 FreeBASIC 已链接 SDL3 库)
#Include "SDL.bi"
' 补充枚举/类型/函数声明(FreeBASIC 绑定可能缺失)
Enum SDL_IOWhence
SDL_IO_SEEK_SET = 0 ' 相对于流开头
SDL_IO_SEEK_CUR = 1 ' 相对于当前位置
SDL_IO_SEEK_END = 2 ' 相对于流末尾
End Enum
Type SDL_IOStream As Any Ptr ' IO 流句柄
Declare Function SDL_IOFromFile CDecl (ByVal path As ZString Ptr, ByVal mode As ZString Ptr) As SDL_IOStream
Declare Function SDL_ReadIO CDecl (ByVal stream As SDL_IOStream, ByVal ptr As Any Ptr, ByVal size As UInteger, ByVal maxnum As UInteger) As UInteger
Declare Function SDL_WriteIO CDecl (ByVal stream As SDL_IOStream, ByVal ptr As Any Ptr, ByVal size As UInteger, ByVal num As UInteger) As UInteger
Declare Function SDL_SeekIO CDecl (ByVal stream As SDL_IOStream, ByVal offset As LongInt, ByVal whence As SDL_IOWhence) As LongInt
Declare Function SDL_TellIO CDecl (ByVal stream As SDL_IOStream) As LongInt
Declare Function SDL_GetIOSize CDecl (ByVal stream As SDL_IOStream) As LongInt
Declare Sub SDL_FlushIO CDecl (ByVal stream As SDL_IOStream)
Declare Sub SDL_CloseIO CDecl (ByVal stream As SDL_IOStream)
Declare Function SDL_IOprintf CDecl (ByVal stream As SDL_IOStream, ByVal fmt As ZString Ptr, ...) As Integer
Declare Function SDL_LoadFile CDecl (ByVal path As ZString Ptr, ByVal size As LongInt Ptr) As Any Ptr
Declare Sub SDL_free CDecl (ByVal ptr As Any Ptr)
' 补充大小端读写函数声明
Declare Function SDL_ReadU8 CDecl (ByVal stream As SDL_IOStream) As UByte
Declare Function SDL_ReadU16LE CDecl (ByVal stream As SDL_IOStream) As UShort
Declare Function SDL_ReadU32LE CDecl (ByVal stream As SDL_IOStream) As UInteger
Declare Function SDL_WriteU8 CDecl (ByVal stream As SDL_IOStream, ByVal value As UByte) As Integer
Declare Function SDL_WriteU16LE CDecl (ByVal stream As SDL_IOStream, ByVal value As UShort) As Integer
Declare Function SDL_WriteU32LE CDecl (ByVal stream As SDL_IOStream, ByVal value As UInteger) As Integer
' 示例1:文件 IO 流读写
Sub FileIOExample()
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "【示例1:文件 IO 流读写】")
' 1. 创建/写入文件
Dim As SDL_IOStream Ptr fileStream = SDL_IOFromFile(StrPtr("test_io.txt"), StrPtr("wb"))
If (fileStream = NULL) Then
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "打开文件失败:%s", SDL_GetError())
Exit Sub
End If
' 写入字符串
Dim As ZString * 100 writeData = "SDL IOStream 测试数据"
Dim As UInteger writeCount = SDL_WriteIO(fileStream, @writeData, 1, Len(writeData))
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "写入字节数:%u(预期:%u)", writeCount, Len(writeData))
' 格式化写入
SDL_IOprintf(fileStream, StrPtr(vbCrLf & "数字:%d,浮点数:%.2f"), 123, 3.14)
' 刷新并关闭
SDL_FlushIO(fileStream)
SDL_CloseIO(fileStream)
' 2. 读取文件
fileStream = SDL_IOFromFile(StrPtr("test_io.txt"), StrPtr("rb"))
If (fileStream = NULL) Then
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "打开文件失败:%s", SDL_GetError())
Exit Sub
End If
' 获取文件大小
Dim As LongInt fileSize = SDL_GetIOSize(fileStream)
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "文件大小:%lld 字节", fileSize)
' 分配缓冲区并读取全部内容
Dim As Any Ptr readBuffer = SDL_malloc(fileSize + 1)
If (readBuffer = NULL) Then
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "内存分配失败")
SDL_CloseIO(fileStream)
Exit Sub
End If
Dim As UInteger readCount = SDL_ReadIO(fileStream, readBuffer, 1, fileSize)
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "读取字节数:%u", readCount)
' 打印读取内容
Dim As ZString Ptr readStr = Cast(ZString Ptr, readBuffer)
readStr[readCount] = 0 ' 确保字符串终止
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "文件内容:%s", *readStr)
' 释放资源
SDL_free(readBuffer)
SDL_CloseIO(fileStream)
End Sub
' 示例2:内存 IO 流操作
Sub MemoryIOExample()
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, vbCrLf & "【示例2:内存 IO 流操作】")
' 1. 准备测试数据(小端序数值)
Dim As UByte byteVal = &HFF
Dim As UShort shortVal = &H1234
Dim As UInteger intVal = &HABCD1234
' 2. 创建内存缓冲区并写入数据
Dim As Byte Ptr memBuffer = Allocate(1024) ' 1KB 缓冲区
Dim As SDL_IOStream Ptr memStream = SDL_IOFromMem(memBuffer, 1024)
If (memStream = NULL) Then
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "创建内存流失败:%s", SDL_GetError())
Deallocate(memBuffer)
Exit Sub
End If
' 写入不同类型数据(小端序)
SDL_WriteU8(memStream, byteVal)
SDL_WriteU16LE(memStream, shortVal)
SDL_WriteU32LE(memStream, intVal)
' 获取当前写入位置
Dim As LongInt writePos = SDL_TellIO(memStream)
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "写入后位置:%lld 字节", writePos)
' 3. 定位到流开头,读取数据
SDL_SeekIO(memStream, 0, SDL_IO_SEEK_SET)
Dim As UByte readByte = SDL_ReadU8(memStream)
Dim As UShort readShort = SDL_ReadU16LE(memStream)
Dim As UInteger readInt = SDL_ReadU32LE(memStream)
' 打印读取结果
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "读取数据:")
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, " 8位无符号整数:0x%02X(预期:0x%02X)", readByte, byteVal)
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, " 16位无符号整数(小端):0x%04X(预期:0x%04X)", readShort, shortVal)
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, " 32位无符号整数(小端):0x%08X(预期:0x%08X)", readInt, intVal)
' 4. 关闭流并释放内存
SDL_CloseIO(memStream)
Deallocate(memBuffer)
End Sub
' 示例3:加载整个文件到内存
Sub LoadFileExample()
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, vbCrLf & "【示例3:加载整个文件到内存】")
Dim As LongInt fileSize = 0
Dim As Any Ptr fileData = SDL_LoadFile(StrPtr("test_io.txt"), @fileSize)
If (fileData = NULL) Then
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "加载文件失败:%s", SDL_GetError())
Exit Sub
End If
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "加载文件大小:%lld 字节", fileSize)
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "文件内容:%s", Cast(ZString Ptr, fileData))
' 释放 SDL_LoadFile 分配的内存
SDL_free(fileData)
End Sub
' 主程序
Sub Main()
' 初始化 SDL
If (SDL_Init(0) < 0) Then
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "SDL 初始化失败:%s", SDL_GetError())
Exit Sub
End If
' 运行示例
FileIOExample()
MemoryIOExample()
LoadFileExample()
' 清理 SDL
SDL_Quit()
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, vbCrLf & "程序正常退出")
End Sub
' 运行主程序
Main()
核心知识点补充
-
IO 流核心特性:
- 抽象性:统一的接口适配不同数据源(文件、内存、自定义流),切换数据源无需修改业务逻辑;
- 定位支持:可通过
SDL_SeekIO/SDL_TellIO实现随机读写,仅部分流(如文件、内存)支持定位; - 大小端适配:内置大端(BE)/小端(LE)数值读写函数,无需手动转换字节序,适配跨平台数据交换。
-
IO 流打开模式规则:
- 与标准 C 库
fopen模式兼容:- "r"/"rb":只读,文件不存在则失败;
- "w"/"wb":只写,创建/覆盖文件;
- "a"/"ab":追加,文件不存在则创建;
- "r+"/"rb+":读写,文件不存在则失败;
- 后缀 "b" 表示二进制模式,避免 Windows 平台的换行符转换。
- 与标准 C 库
-
读写函数返回值规则:
SDL_ReadIO/SDL_WriteIO的参数size是单个数据项的大小,maxnum/num是数据项数量;- 返回值为实际读写的数据项数量(非字节数),例如:
SDL_ReadIO(stream, buf, 4, 10)尝试读取 10 个 4 字节整数,返回 5 表示读取了 5 个(20 字节); - 返回 0 可能表示到达流末尾(EOF)或操作失败,需通过
SDL_GetIOStatus区分。
-
内存流类型差异:
SDL_IOFromConstMem:只读内存流,数据源为 const 指针,不可写;SDL_IOFromMem:可读写内存流,数据源为普通指针,大小固定;SDL_IOFromDynamicMem:动态内存流,自动扩容,适合不确定数据大小的场景。
总结
-
核心优势:
- 统一抽象接口,适配多数据源,降低跨数据源切换成本;
- 内置字节序转换函数,简化跨平台数据读写;
- 提供
SDL_LoadFile/SDL_SaveFile快捷函数,一键加载/保存文件; - 兼容标准 C 库文件操作模式,学习成本低。
-
使用建议:
- 优先使用
SDL_IOFromFile处理文件读写,替代标准 C 库fopen/fread/fwrite; - 读写数值数据时,优先使用大小端专用函数(如
SDL_ReadU32LE),避免字节序错误; - 写入数据后调用
SDL_FlushIO确保数据刷入底层存储,避免缓存丢失; SDL_LoadFile分配的内存必须用SDL_free释放,而非free/Deallocate。
- 优先使用
-
关键接口:
- 流创建:
SDL_IOFromFile()/SDL_IOFromMem()/SDL_IOFromDynamicMem(); - 基础读写:
SDL_ReadIO()/SDL_WriteIO()/SDL_IOprintf(); - 定位操作:
SDL_SeekIO()/SDL_TellIO()/SDL_GetIOSize(); - 快捷操作:
SDL_LoadFile()/SDL_SaveFile(); - 资源管理:
SDL_FlushIO()/SDL_CloseIO()。
- 流创建:
评论一下?