You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C语言跨平台实现自定义缓冲区的类fread流读取功能

跨平台内存二进制读取流实现

直接实现一套基于纯C标准库的内存读取上下文即可,完全不需要依赖平台特定API,行为对齐标准库文件流接口,可直接对接你现有的read/read_buf设计。

核心结构与基础实现

核心逻辑仅维护缓冲区基址、总长度、当前读取偏移三个字段,无额外依赖:

#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

// 内存二进制读取上下文,等价于Python io.BytesIO / C# BinaryReader
typedef struct {
    const uint8_t* base;  // 缓冲区起始地址
    size_t length;        // 缓冲区总长度
    size_t pos;           // 当前读取偏移
} MemReader;

基础操作函数的行为和C标准库文件流接口完全对齐:

// 初始化内存读取器,绑定外部传入的缓冲区,不做内存拷贝
void mem_reader_init(MemReader* reader, const void* buf, size_t size) {
    reader->base = (const uint8_t*)buf;
    reader->length = size;
    reader->pos = 0;
}

// 等价于fread的内存读取实现,返回实际成功读取的元素个数
size_t mem_read(MemReader* reader, void* out, size_t elem_size, size_t elem_count) {
    if (reader->pos > reader->length) {
        return 0;
    }
    size_t remain = reader->length - reader->pos;
    size_t need = elem_size * elem_count;
    size_t copy_len = need > remain ? remain : need;
    if (copy_len > 0 && out != NULL) {
        memcpy(out, reader->base + reader->pos, copy_len);
    }
    reader->pos += copy_len;
    return copy_len / elem_size;
}

// 读取单个基础类型值的便捷宏,返回1表示读取成功、0表示缓冲区越界
#define MEM_READER_READ_ONE(reader, ptr) mem_read((reader), (ptr), sizeof(*(ptr)), 1)

// 跳转读取位置,whence参数和fseek完全一致:支持SEEK_SET/SEEK_CUR/SEEK_END,返回0表示操作成功
int mem_seek(MemReader* reader, long offset, int whence) {
    size_t new_pos;
    switch (whence) {
        case SEEK_SET:
            new_pos = (size_t)offset;
            break;
        case SEEK_CUR:
            new_pos = reader->pos + (size_t)offset;
            break;
        case SEEK_END:
            new_pos = reader->length + (size_t)offset;
            break;
        default:
            return -1;
    }
    if (new_pos > reader->length) {
        return -1;
    }
    reader->pos = new_pos;
    return 0;
}

// 获取当前读取位置,等价于ftell
size_t mem_tell(const MemReader* reader) {
    return reader->pos;
}

// 判断是否读到缓冲区末尾
int mem_eof(const MemReader* reader) {
    return reader->pos >= reader->length;
}

如果需要处理跨平台字节序问题,只需要在基础读取函数上封装对应大小端的读取方法即可,比如mem_read_u32_le、mem_read_u16_be这类,不需要改动核心读取逻辑。

对接现有接口

你原有的函数设计不需要改动,直接按如下逻辑实现即可,全程无平台相关调用:

// 读取整个文件到内存后转交read_buf处理
void* read(const char* filename) {
    FILE* f = fopen(filename, "rb");
    if (!f) return NULL;

    if (fseek(f, 0, SEEK_END) != 0) {
        fclose(f);
        return NULL;
    }
    long file_size = ftell(f);
    if (file_size < 0) {
        fclose(f);
        return NULL;
    }
    rewind(f);

    void* buf = malloc((size_t)file_size);
    if (!buf) {
        fclose(f);
        return NULL;
    }
    size_t read_len = fread(buf, 1, (size_t)file_size, f);
    fclose(f);
    if (read_len != (size_t)file_size) {
        free(buf);
        return NULL;
    }

    void* result = read_buf(buf, (size_t)file_size);
    free(buf); // 如果需要解析后长期持有缓冲区,可移除该行,按自身内存管理逻辑调整
    return result;
}

// read_buf内部使用MemReader逐段解析二进制格式
void* read_buf(const void* buf, size_t size) {
    MemReader reader;
    mem_reader_init(&reader, buf, size);

    // 解析示例:
    // uint32_t file_magic;
    // MEM_READER_READ_ONE(&reader, &file_magic);
    // uint16_t format_version;
    // MEM_READER_READ_ONE(&reader, &format_version);
    // 其余字段解析逻辑...

    return NULL; // 替换为实际解析结果的返回逻辑
}

方案特性

  • 完全兼容C89及以上标准,全平台通用,无第三方依赖
  • 零额外内存拷贝,读取器仅持有缓冲区指针,运行开销极低
  • 接口和标准库文件流操作对齐,学习成本为零
  • 可灵活扩展变长字符串读取、字节序转换等二进制解析常用能力

内容的提问来源于stack exchange,提问作者demberto

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.29 08:45:17