你能用FILE *写一个字节数组吗?

时间:2009-07-19 19:10:50

标签: c

C#具有能够使用MemoryStream对象写入内存流的简洁功能。

我正在使用FILE *指针从C中寻找类似的功能。

我希望能够sprintf(),但是在我正在写入的缓冲区中添加了C记住“我在哪里”的功能。

6 个答案:

答案 0 :(得分:5)

如果您使用的是GNU C库,则可以使用fmemopen()。其他环境可能还有其他非可移植扩展,但没有使用FILE *的可移植方式。

但是,如果你不坚持实际使用FILE *,你也可以包装snprintf。例如,glib(注意:与GNU C库不同,并且可移植)具有g_string_append_printf,可以满足您的需求。

答案 1 :(得分:3)

还有一个丑陋的黑客可以使用普通的ISO-C:您可以使用fopen()打开一个空文件(* /dev/null在* nix上,NUL在Windows上)并设置数组作为文件的缓冲区通过

setvbuf(file, buffer, _IOFBF, buffer_size)

只要代码中的任何地方都没有调用fflush(),这应该可以正常工作。此外,程序员必须明确地处理字符串分隔符。

我并不认为有必要这样做:当snprintf()返回写入的字符数时,跟踪缓冲区的位置是微不足道的。

甚至可以编写一个函数来在溢出时自动调整缓冲区的大小:bufprintf.c

该函数的原型是

int bufprintf(char **buffer, size_t *size, size_t *offset,
    const char *format, ...);

示例程序可能如下所示:

#include <stdio.h>

extern int bufprintf(char **buffer, size_t *size, size_t *offset,
    const char *format, ...);

int main(void)
{
    size_t size = 0; // must be set!
    size_t offset;
    char * buffer;

    for(int i = 0; i < 100; ++i)
        bufprintf(&buffer, &size, &offset, "we rock %i\n", i);

    puts(buffer);
    printf("size:\t%u\noffset:\t%u\n", (unsigned)size, (unsigned)offset);
}

答案 2 :(得分:2)

sprintf返回打印到字符串中的字符数。您可以使用该值来递增缓冲区的指针。

buffer += sprintf(buffer, "%d", i);

确保保留原始指针的副本,因为这是在将缓冲区传递到其他位置时将使用的内容。

答案 3 :(得分:0)

为什么不使用mmap?您可以将文件映射到内存并使用FILE *指针。

更新:它不起作用。遗憾。

答案 4 :(得分:0)

MemoryStream不是语言C#的一个功能。它只是BCL中的一个类。你可以在C#中自己编写。

所以它在C中 - 您可以编写一些功能类似于fopenfprintffwritefclose等的功能,但是给他们一些名字,如mopenmwrite等(大概)并写下来,使它们在内存缓冲区上运行。

答案 5 :(得分:0)

如何手动管理指针呢?我前面没有编译器,但希望下面的代码可以解决这个问题:

char huge_buffer[REALLY_BIG_SIZE];
char *write_pos = huge_buffer;

//...

void fprintf_to_mem(char **mem_ptr, const char *fmt, ...)
{
  va_list args;
  int num_written;

  va_start(args, mem_ptr);
  num_written = vsprintf(*write_pos, fmt, args);
  *write_pos += num_written;

  va_end(args);
}

//...

fprintf_to_mem(&write_pos, "Testing %d %d %d", 1, 2, 3);
fprintf_to_mem(&write_pos, "Hello world!\r\n");  

我希望输出“Testing 1 2 3Hello world!\ r \ n”到huge_buffer。