如何在C中将XML文件读入缓冲区?

我想用C语言将XML文件读入char *buffer

做这个的最好方式是什么?

我应该如何开始?

正在读取文件的内容到一个简单的缓冲区真的你想做什么? XML文件通常需要解析,你可以使用像libxml2这样的库来实现,只是举一个例子(但值得注意的是,用C实现)。

如果你想解析 XML,不只是将它读入缓冲区(某些不是特定于XML的,请参阅Christoph和Baget的答案),你可以使用例如libxml2 :

 #include  #include  #include  int main(int argc, char **argv) { xmlDoc *document; xmlNode *root, *first_child, *node; char *filename; if (argc < 2) { fprintf(stderr, "Usage: %s filename.xml\n", argv[0]); return 1; } filename = argv[1]; document = xmlReadFile(filename, NULL, 0); root = xmlDocGetRootElement(document); fprintf(stdout, "Root is <%s> (%i)\n", root->name, root->type); first_child = root->children; for (node = first_child; node; node = node->next) { fprintf(stdout, "\t Child is <%s> (%i)\n", node->name, node->type); } fprintf(stdout, "...\n"); return 0; } 

在Unix机器上,您通常使用以下代码编译上述内容:

 % gcc -o read-xml $(xml2-config --cflags) -Wall $(xml2-config --libs) read-xml.c 

希望无错误的ISO-C代码读取文件的内容并添加’\ 0’字符:

 #include  #include  long fsize(FILE * file) { if(fseek(file, 0, SEEK_END)) return -1; long size = ftell(file); if(size < 0) return -1; if(fseek(file, 0, SEEK_SET)) return -1; return size; } size_t fget_contents(char ** str, const char * name, _Bool * error) { FILE * file = NULL; size_t read = 0; *str = NULL; if(error) *error = 1; do { file = fopen(name, "rb"); if(!file) break; long size = fsize(file); if(size < 0) break; if(error) *error = 0; *str = malloc((size_t)size + 1); if(!*str) break; read = fread(*str, 1, (size_t)size, file); (*str)[read] = 0; *str = realloc(*str, read + 1); if(error) *error = (size != (long)read); } while(0); if(file) fclose(file); return read; } 

您可以使用stat()函数来获取文件大小。 然后在使用fread读取文件后使用malloc分配缓冲区。

代码将是这样的:

 struct stat file_status; char *buf = NULL; FILE * pFile; stat("tmp.xml", &file_status); buf = (char*)malloc(file_status.st_size); pFile = fopen ("tmp.xml","r"); fread (buf,1,file_status.st_size,pFile); fclose(pFile); 
  1. 在Visual Studio中将libxml2安装为NuGet包(我使用的是Vs 2015来测试它)
  2. 将示例XML文件下的内容复制并粘贴到记事本中,并将该文件另存为example.xml
  3. 复制并通过// xml解析到Vs下的代码
  4. 使用xml文件名作为参数从main调用函数
  5. 您将在configReceive中获取xml数据

就这样…

示例XML文件:

          

这是源代码:

 #include  #include  #include  #include  #include  #include  char configReceive[6][80] = { " " }; //xml parsing void ParsingXMLFile(char *filename) { char *docname; xmlDocPtr doc; xmlNodePtr cur; xmlChar *uri; char config[6][80] = { "value1", "value2", "value3", "value4", "value5", "value6" }; int count = 0; int count1 = 0; docname = filename; doc = xmlParseFile(docname); cur = xmlDocGetRootElement(doc); cur = cur->xmlChildrenNode; while (cur != NULL) { if ((!xmlStrcmp(cur->name, (const xmlChar *)"xmlConfig"))) { uri = xmlGetProp(cur, (xmlChar *)config[count++]); strcpy(configReceive[count1++], (char *)uri); xmlFree(uri); } cur = cur->next; } count = 0; count1 = 0; xmlFreeDoc(doc); } 

这是一个完整的程序,它将整个XML文件(实际上是任何文件)读入缓冲区。 它包括尽可能多的错误检查。

NB一切都在main() 。 将其转换为可调用的function留给读者练习。

(经过测试,用GCC 4.3.3编译。开关是-Wall -W --pedantic --ansi 。)

对此的评论将在大约八小时内得到解决。

 #include  #include  int main (int argc, char *argv[]) { char *buffer; /* holds the file contents. */ size_t i; /* indexing into buffer. */ size_t buffer_size; /* size of the buffer. */ char *temp; /* for realloc(). */ char c; /* for reading from the input. */ FILE *input; /* our input stream. */ if (argc == 1) { fprintf(stderr, "Needs a filename argument.\n"); exit(EXIT_FAILURE); } else if (argc > 2) { fprintf(stderr, "Well, you passed in a few filenames, but I'm only using %s\n", argv[1]); } if ((input = fopen(argv[1], "r")) == NULL) { fprintf(stderr, "Error opening input file %s\n", argv[1]); exit(EXIT_FAILURE); } /* Initial allocation of buffer */ i = 0; buffer_size = BUFSIZ; if ((buffer = malloc(buffer_size)) == NULL) { fprintf(stderr, "Error allocating memory (before reading file).\n"); fclose(input); } while ((c = fgetc(input)) != EOF) { /* Enlarge buffer if necessary. */ if (i == buffer_size) { buffer_size += BUFSIZ; if ((temp = realloc(buffer, buffer_size)) == NULL) { fprintf(stderr, "Ran out of core while reading file.\n"); fclose(input); free(buffer); exit(EXIT_FAILURE); } buffer = temp; } /* Add input char to the buffer. */ buffer[i++] = c; } /* Test if loop terminated from error. */ if (ferror(input)) { fprintf(stderr, "There was a file input error.\n"); free(buffer); fclose(input); exit(EXIT_FAILURE); } /* Make the buffer a bona-fide string. */ if (i == buffer_size) { buffer_size += 1; if ((temp = realloc(buffer, buffer_size)) == NULL) { fprintf(stderr, "Ran out of core (and only needed one more byte too ;_;).\n"); fclose(input); free(buffer); exit(EXIT_FAILURE); } buffer = temp; } buffer[i] = '\0'; puts(buffer); /* Clean up. */ free(buffer); fclose(input); return 0; } 

我相信这个问题是关于XML解析而不是文件阅读,但OP应该真正澄清这一点。
你有什么方法可以看到如何阅读文件。
除了sgm建议之外,xml解析的另一个选项是Expat库

建议:使用内存映射

这有可能减少无用的数据复制。 诀窍是询问操作系统你想要什么,而不是这样做。 这是我之前做的一个实现:

mmap.h

 #ifndef MMAP_H #define MMAP_H #include  struct region_t { void *head; off_t size; }; #define OUT_OF_BOUNDS(reg, p) \ (((void *)(p) < (reg)->head) || ((void *)(p) >= ((reg)->head)+(reg)->size)) #define REG_SHOW(reg) \ printf("h: %p, s: %ld (e: %p)\n", reg->head, reg->size, reg->head+reg->size); struct region_t *do_mmap(const char *fn); #endif 

mmap.c

 #include  #include  /* open lseek */ #include  /* open */ #include  /* open */ #include  /* lseek */ #include  /* mmap */ #include "mmap.h" struct region_t *do_mmap(const char *fn) { struct region_t *R = calloc(1, sizeof(struct region_t)); if(R != NULL) { int fd; fd = open(fn, O_RDONLY); if(fd != -1) { R->size = lseek(fd, 0, SEEK_END); if(R->size != -1) { R->head = mmap(NULL, R->size, PROT_READ, MAP_PRIVATE, fd, 0); if(R->head) { close(fd); /* don't need file-destructor anymore. */ return R; } /* no clean up of borked (mmap,) */ } close(fd); /* clean up of borked (lseek, mmap,) */ } free(R); /* clean up of borked (open, lseek, mmap,) */ } return NULL; }