【问题标题】:Parsing a csv file having comma separated value in single column using C使用C解析在单列中具有逗号分隔值的csv文件
【发布时间】:2017-01-25 02:24:39
【问题描述】:

我必须从 CSV 文件中读取数据并在我的 C 函数中使用这些值。

我正在使用以下代码进行此操作:

int arg1;
char arg2[500];
int arg3;
FILE *file;
file=fopen(filename,"r");
if (file == NULL)
{
    printf("Not able to open the file\n");
}
while (fgets(line,1000, file)!=NULL)
    {
            splitline=strtok(line,",");
            while(splitline)
            {
                if(firstargument==1)
                {
                    arg1=atoi(splitline);
                    printf("First argument is %d ",arg1);
                    firstargument=2;
                }
                else if(firstargument==2)
                {
                    splitline[strlen(splitline)]='\0';
                    strcpy(arg2,splitline);
                    printf("Second argument is %s\n",arg2);
                    firstargument=3;
                }
                else
                {
                    arg3=atoi(splitline);
                    printf("Third argument is %d ",arg1);
                    firstargument=1;
                }
                splitline = strtok(NULL,",");
            }
            printf("Value to insert Key:%d,Value:%s,Height:%d\n",arg1,arg2,arg3);
            inserth(inode,arg1,arg2,arg3);
        }

但是当我的 csv 文件的单列包含多个逗号分隔值时 解析失败

350206,Uma,1
350207,Umika,1
350208,"Vaishavi, Vaishnodevi",1
350226,Badriprasad,1
350227,"Kanak, Kanaka",1

有没有办法读取csv文件单列中的多个值?

【问题讨论】:

  • 这不是错误,只是参数值输入错误,因为如果我读到第 350227 行,"Kanak, Kanaka",1 my arg1 =350277 arg2="Kanak arg3= Kanaka" 所以你可以如果 arg2=Kanak, Kanaka arg3=1,请参阅 arg3 得到错误值正确
  • 您的解析不考虑 " 块,同时使用 strtok() 使用简单的逗号分隔。
  • 也许使用开源 C 库,例如 github.com/liquidaty/zsv 的库 + CLI

标签: c csv


【解决方案1】:

试试这个

if (file == NULL){
    perror("Not able to open the file\n");
    exit(EXIT_FAILURE);
}
while (fgets(line,1000, file)!=NULL){
    if( 3==sscanf(line, "%d,\"%499[^\"]\",%d", &arg1, arg2, &arg3) || //pattern 1
        3==sscanf(line, "%d,%499[^,],%d",      &arg1, arg2, &arg3)){  //pattern 2
        printf("Value to insert Key:%d,Value:%s,Height:%d\n",arg1,arg2,arg3);
        inserth(inode,arg1,arg2,arg3);
    } else {
        fprintf(stderr, "invalid format\n");
        exit(EXIT_FAILURE);
    }
}

【讨论】:

    【解决方案2】:

    一种解决方案是实现您自己的尊重双引号的strtokstrtok 本身实现起来非常简单:

    char * tokenise( char *str, const char *delim )
    {
        static char *next = NULL;
        if( str ) next = str;
        if( !*next ) return NULL;
        str = next;
        while( !strchr( delim, *next ) ) next++;
        if( *next ) *next++ = 0;
        return str;
    }
    

    现在,这是一般情况。你只关心逗号,而在双引号的情况下,你只关心双引号:

    char * tokenise( char *str )
    {
        static char *next = NULL;
        if( str ) next = str;
        if( !*next ) return NULL;
        str = next;
    
        if( *str == '"' ) {
           str++;
           next++;
           while( *next && *next != '"' ) next++;
           if( *next == '"' ) *next++ = 0;
        }
    
        while( *next && *next != ',' ) next++;
        if( *next ) *next++ = 0;
        return str;
    }
    

    这很幼稚,但应该可以解决问题。它在第一个字符中检测到",将其删除,然后扫描到下一个"。它不处理转义引号、CSV 字段之间的空格或语法错误(例如出现在右引号之后的非逗号字符 - 它会丢弃它们),但您明白了。

    【讨论】:

      【解决方案3】:

      首先,对于 csv 文件,如果逗号包含在双引号中,通常意味着应该忽略逗号。这意味着每一行只有 3 个值(3 列)。

      由于您只有两种类型的行,一种带双引号,一种不带双引号,因此简单的 if-else 语句在这里会有所帮助

      我使用strsep 而不是strtok。我也在逐行读取文件。

      #include <string.h>
      #include <stdio.h>
      
      int main()
      
          {
          FILE *file;
          char *splitline;
          char * line = NULL;
          size_t len = 0;
          ssize_t read;
          file=fopen(filename,"r");
          if (file == NULL)
          {
          printf("Not able to open the file\n");
          }
           while ((read = getline(&line, &len, file)) != -1) 
              {
                  if(strstr(line,"\"") != NULL)
      
                  {
                  printf("%s\n",line);
                          splitline=strsep(&line,",");
                      printf("%s : %s\n",splitline,line);
                          line = line+1;  // avoiding first doublequotes("), you may use strsep twice instead
                          splitline = strsep(&line,"\"");
                      printf("%s : %s\n",splitline,line);
                          line = line+1;   // removing comma and rest is the 3rd entry
                      printf("%s",line);
                           }
      
                         else
                        {
      
      
                         //Routine code that expects two commas and three values
      
                         }
      
                }
          }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-11-29
        • 2016-06-22
        • 2013-04-19
        • 2017-08-29
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多