Как я могу прочитать XML-файл в буфер в C?

Я хочу прочитать XML-файл в char *buffer используя C.

Каков наилучший способ сделать это?

Как мне начать?

Является ли чтение содержимого файла в единый простой буфер действительно тем, что вы хотите сделать? XML-файлы, как правило, должны быть проанализированы, и вы можете сделать это с помощью библиотеки libxml2 , просто чтобы привести один пример (но, в частности, реализован на C).

И если вы хотите анализировать XML, а не просто читать его в буфер (что-то, что не было бы специфичным для XML, см. Ответы Кристофа и Багета), вы можете использовать, например, 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; } в #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 (), чтобы получить размер файла. затем выделите буфер, используя malloc, после чтения файла с использованием fread.

код будет примерно таким:

 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. Установите libxml2 как пакет NuGet в Visual Studio (я использую Vs 2015 для проверки этого)
  2. Скопируйте и вставьте содержимое в пример XML-файла в блокнот и сохраните файл как example.xml
  3. Скопируйте и запустите код в разделе // xml в Vs
  4. Вызовите функцию main с именем файла xml в качестве аргумента
  5. Вы получите данные xml в configReceive

Это все…

пример 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() . Преrotation его в вызываемую функцию остается в качестве упражнения для читателя.

(Протестировано, скомпилировано с 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; } 

Я считаю, что этот вопрос касался parsingа XML, а не чтения файла, однако OP действительно должен это прояснить.
В любом случае у вас есть много примеров того, как читать файл.
Другим вариантом анализа xml в дополнение к предложению sgm будет библиотека 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; }