3

我的任务是更新当前从磁盘读取配置文件并填充结构的函数:

static int LoadFromFile(FILE *Stream, ConfigStructure *cs)
{
  int tempInt;

   ...

  if ( fscanf( Stream, "Version: %d\n",&tempInt) != 1 )
  {
    printf("Unable to read version number\n");
    return 0;
  }
  cs->Version = tempInt;
   ...

}

一个允许我们绕过将配置写入磁盘而直接将其传递到内存中的方法,大致相当于:

static int LoadFromString(char *Stream, ConfigStructure *cs)

需要注意的几点:

  • 当前的 LoadFromFile 函数非常密集和复杂,以向后兼容的方式读取数十个版本的配置文件,这使得整体逻辑的重复非常痛苦。
  • 生成配置文件的函数和读取它的函数来自旧系统的完全不同的部分,因此不共享任何数据结构,所以我不能直接传递它们。我可能会编写一个包装器,但同样,它需要以向后兼容的方式处理传入的任何结构。
  • 我很想将文件按原样作为字符串传递(如上面的原型中)并将所有 fscanf 转换为 sscanf 但我必须手动处理指针的递增(并可能处理缓冲区溢出错误)。
  • 这必须保留在 C 中,因此没有像流这样的 C++ 功能可以在这里提供帮助

我错过了更好的选择吗?有没有办法创建一个实际上只是指向内存而不是磁盘的位置的 FILE *?非常感谢任何指针、建议或其他帮助。

4

3 回答 3

3

如果您不能传递结构并且必须将数据作为字符串传递,那么您应该能够调整函数以从字符串而不是文件中读取。如果函数像您描述的那样复杂,那么转换fscanf->sscanf可能是最直接的方法。

这是使用上面的函数原型的一个想法。读入整个数据字符串(不处理任何数据)并将其存储在本地缓冲区中。这样,代码可以像使用文件一样随机访问数据,并使缓冲区溢出更容易预测和避免。首先malloc创建一个大小合理的缓冲区,将数据复制到其中,并realloc根据需要为您自己提供更多空间。一旦您拥有整个数据缓冲区的本地副本,请扫描它并提取您需要的任何数据。

请注意,如果'\0'字符是有效输入,这可能会变得棘手。在这种情况下,您必须添加额外的逻辑来测试这是输入字符串的结尾还是零字节(难度取决于数据缓冲区的特定格式)。

于 2010-03-15T22:06:06.770 回答
2

由于您试图将文件数据保存在内存中,因此您应该能够使用共享内存。POSIX 共享内存实际上是映射内存的一种变体。如有必要,可以使用mmap()将共享内存对象映射到进程地址空间。共享内存通常用作 IPC 机制,但您应该能够根据自己的情况使用它。

以下示例代码结合使用 POSIX 共享内存(shm_open()shm_unlink()FILE *将文本写入共享内存对象,然后将其读回。

#include <fcntl.h>
#include <stdio.h>
#include <sys/mman.h>
#include <sys/types.h>

#define MAX_LEN 1024

int main(int argc, char ** argv)
{
    int    fd;
    FILE * fp;
    char * buf[MAX_LEN];

    fd = shm_open("/test", O_CREAT | O_RDWR, 0600);

    ftruncate(fd, MAX_LEN);

    fp = fdopen(fd, "r+");

    fprintf(fp, "Hello_World!\n");

    rewind(fp);

    fscanf(fp, "%s", buf);

    fprintf(stdout, "%s\n", buf);

    fclose(fp);

    shm_unlink("/test");

    return 0;
}

-lrt注意:在 Linux 上使用 gcc 编译此示例时,我必须传递给链接器。

于 2010-03-16T17:00:22.607 回答
1
  • 用于mkstemp()创建临时文件。它char *作为参数并将其用作文件名的模板。但是,它将返回一个文件描述符。

  • 使用tmpfile(). 它返回FILE *,但存在一些安全问题,而且您必须自己复制字符串。

  • 使用mmap()Beej 的帮助指南)

于 2010-03-15T21:53:14.440 回答