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

时间:2008-12-19 15:33:27

标签: c xml

我想使用C。

将XML文件读入char *buffer

这样做的最佳方式是什么?

我该如何开始?

8 个答案:

答案 0 :(得分:7)

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

答案 1 :(得分:6)

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

#include <stdio.h>
#include <string.h>
#include <libxml/parser.h>

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

答案 2 :(得分:3)

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

#include <stdlib.h>
#include <stdio.h>

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;
}

答案 3 :(得分:2)

您可以使用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);

答案 4 :(得分:1)

  1. 在Visual Studio中将libxml2安装为NuGet包(我使用Vs 2015进行测试)
  2. 将示例XML文件中的内容复制并粘贴到记事本中,并将文件另存为example.xml
  3. 复制并通过// xml解析到Vs
  4. 下的代码
  5. 使用xml文件名作为参数从main调用函数
  6. 您将在configReceive
  7. 中获取xml数据

    这就是......

    示例XML文件:

    <?xml version="1.0" encoding="utf-8"?>
        <config>
            <xmlConfig value1="This is a simple XML parsing program in C"/>
            <xmlConfig value2="Thank you : Banamali Mishra"/>
            <xmlConfig value3="2000000"/>
            <xmlConfig value4="80"/>
            <xmlConfig value5="10"/>
            <xmlConfig value6="1"/>
        </config>
    

    以下是源代码:

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <libxml/xmlreader.h>
    #include <libxml/xmlmemory.h>
    #include <libxml/parser.h>
    
    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);
    }
    

答案 5 :(得分:0)

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

N.B。一切都在main()完成。把它变成一个可调用的函数留给读者练习。

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

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

#include <stdio.h>
#include <stdlib.h>


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;
}

答案 6 :(得分:0)

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

答案 7 :(得分:0)

建议:使用内存映射

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

mmap.h

#ifndef MMAP_H
#define MMAP_H

#include <sys/types.h>

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 <stdlib.h>

#include <sys/types.h>  /* open lseek             */
#include <sys/stat.h>   /* open                   */
#include <fcntl.h>      /* open                   */
#include <unistd.h>     /*      lseek             */
#include <sys/mman.h>   /*            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;
}