代码之家  ›  专栏  ›  技术社区  ›  Dusty

将函数转换为从字符串而不是C中的文件读取

  •  3
  • Dusty  · 技术社区  · 16 年前

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

    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++功能可以帮助这里。

    我错过了更好的选择吗?有没有办法创建一个文件*,它实际上只是指向内存中的一个位置而不是磁盘上的一个位置?任何建议、建议或其他帮助都将受到极大的赞赏。

    3 回复  |  直到 16 年前
        1
  •  2
  •   jschmier    16 年前

    由于您试图将文件数据保存在内存中,因此应该能够使用 shared memory . 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编译此示例时,指向链接器。

        2
  •  3
  •   bta    16 年前

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

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

    注意,如果 '\0' 字符是有效输入。在这种情况下,如果这是输入字符串的结尾或者只是一个零字节(困难取决于数据缓冲区的特定格式),则必须添加额外的逻辑来测试。

        3
  •  1
  •   N 1.1    16 年前