2011-02-15 96 views
2

考慮,這條消息:如何使用引號分隔C中分隔字段的CSV?

N,8545,01/02/2011 09:15:01.815,"RASTA OPTSTK 24FEB2011 1,150.00 CE",S,8.80,250,0.00,0 

這僅僅是一個樣品。這個想法是,這是一個csv文件中的行。現在,如果我要把它分成逗號,那麼1150的數字就會出現問題。

雙引號內的字符串的長度是可變的,但是可被確定爲一個「元件」(如果我可使用術語) 其它元件由分離的那些,

我如何解析它? (除Ragel解析引擎)

Soham

+1

你所擁有的是一個「可選地」用引號括起來的字段。請參閱http://programmers.stackexchange.com/questions/26284/best-way-to-handle-delimited-files,http://stackoverflow.com/questions/4479977/csv-parsing-for-embedded-double- quotes ,http://stackoverflow.com/questions/736629/parse-delimited-csv-in-net,和其他許多人。 – JYelton 2011-02-15 21:11:24

+0

誰冒充地獄決定逃避逗號和雙引號雙引號?生活,如果更有趣的話,將是一個有點無聊 – Soham 2011-02-15 21:28:55

回答

1

,如果你不希望添加外部庫將轉換雙引號\ 0(字符串標記的結尾)一個快速和骯髒的解決方案,然後解析三個字符串分別使用sscanf。醜陋但應該工作。

假設輸入是格式良好的(否則你就必須添加錯誤處理):

for (i=0; str[i]; i++) 
    if (str[i] == '"') str[i] = 0; 
str += sscanf(str, "%c,%d,%d/%d/%d %d:%d:%d.%d,", &var1, &var2, ..., &var9); 
var10 = str; // it may be str+1, I don't remember if sscanf consumes also the \0 
sscanf(str+strlen(var10), ",%c,%f,%d,%f,%d", &var11, &var12, ..., &var15); 

你顯然必須作出的var10副本,如果你想立即釋放str

3

將字符串拆分爲以逗號分隔的字段提供的逗號未嵌入在帶引號的字符串中。

一個快速的方法是使用狀態機。

boolean inQuote = false; 
StringBuffer buffer= new StringBuffer(); 
// readchar() is to be implemented however you read a char 
while ((char = readchar()) != -1) { 
    switch (char) { 

    case ',': 
     if (inQuote == false) { 
     // store the field in our parsedLine object for later processing. 
     parsedLine.addField(buffer.toString()); 
     buffer.setLength(0); 
     } 
     break; 

    case '"': 
     inQuote = !inQuote; 
     // fall through to next target is deliberate. 

    default: 
     buffer.append(char); 

    } 
} 

注意的是,雖然這提供了一個例子,還有更多的將必須被考慮(引號內如嵌入式引號,或者它是否適合你的榜樣剝離外引號)CSV文件位。

+0

你在.NET語言中說話嗎?我認爲``parsedLine.addField()`東西在Linux上不起作用 – Soham 2011-02-15 21:30:49

0

這是一個函數,用於從輸入文件中獲取下一個單個CSV字段,作爲FILE *提供。它希望文件以文本模式打開,並且支持帶嵌入引號和換行符的引用字段。超過所提供緩衝區大小的字段被截斷。

int get_csv_field(FILE *f, char *buf, size_t size) 
{ 
    char *p = buf; 
    int c; 
    enum { QS_UNQUOTED, QS_QUOTED, QS_GOTQUOTE } quotestate = QS_UNQUOTED; 

    if (size < 1) 
     return EOF; 

    while ((c = getc(f)) != EOF) 
    { 
     if ((c == '\n' || c == ',') && quotestate != QS_QUOTED) 
      break; 

     if (c == '"') 
     { 
      if (quotestate == QS_UNQUOTED) 
      { 
       quotestate = QS_QUOTED; 
       continue; 
      } 

      if (quotestate == QS_QUOTED) 
      { 
       quotestate = QS_GOTQUOTE; 
       continue; 
      } 

      if (quotestate == QS_GOTQUOTE) 
      { 
       quotestate = QS_QUOTED; 
      } 
     } 

     if (quotestate == QS_GOTQUOTE) 
     { 
      quotestate = QS_UNQUOTED; 
     } 

     if (size > 1) 
     { 
      *p++ = c; 
      size--; 
     } 
    } 

    *p = '\0'; 

    return c; 
} 
相關問題