gpt4 book ai didi

c++ - C 中优雅的二进制 i/o?

转载 作者:太空宇宙 更新时间:2023-11-04 02:18:23 27 4
gpt4 key购买 nike

我最近一直在使用 C/C++ 加载大量二进制文件,我为它的不雅而烦恼。要么我得到很多看起来像这样的代码(我已经继续前进):

uint32_t type, k;
uint32_t *variable;
FILE *f;

if (!fread(&type, 4, 1, f))
goto boundsError;

if (!fread(&k, 4, 1, f))
goto boundsError;

variable = malloc(4 * k);
if (!fread(variable, 4 * k, 1, f))
goto boundsError;

或者,我定义一个本地的打包结构,以便我可以更轻松地读取常量大小的 block 。然而,在我看来,对于这样一个简单的问题——即将指定的文件读入内存——可以更有效地以更易读的方式完成。有没有人有任何提示/技巧等?我想澄清一下,我不是在寻找图书馆或其他东西来处理这个问题;如果我正在设计我自己的文件并且必须大量更改文件规范,我可能会很感兴趣,但现在我只是在寻找风格上的答案。

另外,有些人可能会建议 mmap——我喜欢 mmap!我经常使用它,但它的问题是它会导致处理未对齐数据类型的令人讨厌的代码,这在使用 stdio 时并不存在。最后,我会编写类似 stdio 的包装函数来从内存中读取数据。

谢谢!

编辑:我还应该澄清一下,我不能更改文件格式——我必须阅读一个二进制文件;我无法请求其他格式的数据。

最佳答案

对于这个问题,我见过的最优雅的解决方案是 Sean Barrett 的 writefv ,用于他的微型图像写入库 stb_image_write可用here .他只实现了一些原语(没有错误处理),但同样的方法可以扩展到基本上是二进制的 printf。 (对于阅读,您可以做同样的事情来获得二进制 scanf )。非常优雅整洁!事实上,整个事情是如此简单,我不妨把它包括在这里:

static void writefv(FILE *f, const char *fmt, va_list v)
{
while (*fmt) {
switch (*fmt++) {
case ' ': break;
case '1': { unsigned char x = (unsigned char) va_arg(v, int); fputc(x,f); break; }
case '2': { int x = va_arg(v,int); unsigned char b[2];
b[0] = (unsigned char) x; b[1] = (unsigned char) (x>>8);
fwrite(b,2,1,f); break; }
case '4': { stbiw_uint32 x = va_arg(v,int); unsigned char b[4];
b[0]=(unsigned char)x; b[1]=(unsigned char)(x>>8);
b[2]=(unsigned char)(x>>16); b[3]=(unsigned char)(x>>24);
fwrite(b,4,1,f); break; }
default:
assert(0);
return;
}
}
}

下面是他如何使用它编写真彩色 .BMP 文件:

static int outfile(char const *filename, int rgb_dir, int vdir, int x, int y, int comp, void *data, int alpha, int pad, const char *fmt, ...)
{
FILE *f;
if (y < 0 || x < 0) return 0;
f = fopen(filename, "wb");
if (f) {
va_list v;
va_start(v, fmt);
writefv(f, fmt, v);
va_end(v);
write_pixels(f,rgb_dir,vdir,x,y,comp,data,alpha,pad);
fclose(f);
}
return f != NULL;
}

int stbi_write_bmp(char const *filename, int x, int y, int comp, const void *data)
{
int pad = (-x*3) & 3;
return outfile(filename,-1,-1,x,y,comp,(void *) data,0,pad,
"11 4 22 4" "4 44 22 444444",
'B', 'M', 14+40+(x*3+pad)*y, 0,0, 14+40, // file header
40, x,y, 1,24, 0,0,0,0,0,0); // bitmap header
}

(write_pixels 的定义被省略,因为它在这里非常切线)

关于c++ - C 中优雅的二进制 i/o?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4175754/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com