a亚洲精品_精品国产91乱码一区二区三区_亚洲精品在线免费观看视频_欧美日韩亚洲国产综合_久久久久久久久久久成人_在线区

首頁 > 編程 > C > 正文

標(biāo)準(zhǔn)CSV格式的介紹和分析以及解析算法實(shí)例詳解

2020-01-26 14:22:23
字體:
供稿:網(wǎng)友

     CSV是一種古老的數(shù)據(jù)傳輸格式,它的全稱是Comma-Separated Values(逗號分隔值)。出生在那個(gè)標(biāo)準(zhǔn)缺失的蠻荒年代,CSV的標(biāo)準(zhǔn)一直(到2005年)是NULL――世間存在著N種CSV格式,它們自成體系,相互不兼容。比如我們從名字可以認(rèn)為CSV至少是一種使用逗號分隔的格式,但是實(shí)際上,有的CSV格式卻是使用分號(;)去做分隔。假如,不存在一種標(biāo)準(zhǔn),那么這東西最終會(huì)因?yàn)樗槠l(fā)展緩慢,甚至沒落。本文討論的CSV格式是基于2005年發(fā)布的RFC4180規(guī)范。我想,在這個(gè)規(guī)范發(fā)布之后,大家應(yīng)該會(huì)更加自覺的遵從這套規(guī)范去開發(fā)――雖然這套標(biāo)準(zhǔn)依舊存在著一些致命的缺陷

        我們可以從IETF上獲得包含了CSV格式定義的文檔。當(dāng)然,如果你覺得看英文文檔麻煩,你可以直接看我的下文。

1.在不包含換行符(CRLF即 /r/n)的單條信息時(shí),數(shù)據(jù)要保持在一行,并且使用/r/n結(jié)束。

aaa,bbb,ccc,dddCRLF   合法

aaa,b                            內(nèi)容中無換行符,而單條信息被換行,不合法

bb.ccc,dddCRLF

2.最后一條信息可以沒有換行符(當(dāng)然有換行符也是合法的)

aaa,bbb,ccc,dddCRLF

eee,fff,ggg,hhh           合法

aaa,bbb,ccc,dddCRLF
eee,fff,ggg,hhhCRLF     合法

3.第一條信息可能是一個(gè)頭信息。這個(gè)頭信息和之后信息格式是相同的,并且和之后的信息有相同的模塊數(shù)(上例中,aaa和bbb和ccc和ddd各被視為一個(gè)模塊)。(個(gè)人認(rèn)為這是RFC設(shè)計(jì)這個(gè)CSV格式的一個(gè)缺陷,因?yàn)檫@個(gè)規(guī)則將無法讓我們從規(guī)則的角度去確認(rèn)第一條信息到底是頭信息還是普通信息。當(dāng)然RFC這么設(shè)計(jì)肯定有它的原因。)

index,character          合法,從字面意思上我們可以認(rèn)為這個(gè)是頭,當(dāng)然我們也可以認(rèn)為它不是頭

1,aCRLF
2,bCRLF

indexCRLF                 非法,模塊數(shù)不統(tǒng)一
1,aCRLF

4.每條信息都要使用半角逗號(,)分隔出若干模塊。每條信息的模塊數(shù)要相等。每條信息的最后一個(gè)模塊之后不可以使用半角逗號。空格符被視為一個(gè)模塊的內(nèi)容而不可被忽略。(這條規(guī)則包含的信息量相對較多)

aaa,bbbCRLF                合法
ccc,ddd,CRLF                非法,一條信息的最后一個(gè)模塊不可以使用半角逗號
eee;ffffCRLF                   非法,要使用半角逗號分隔,而不是分號
ggg,       h h h  CRLF     合法,注意hhh模塊的若干個(gè)空格,它屬于模塊內(nèi)容而不可以被忽略
iii,jjj,kkkkCRLF               非法,模塊數(shù)和上面不統(tǒng)一

5.每個(gè)模塊首尾可以使用雙引號擴(kuò)住(當(dāng)然也可以不使用)。如果不使用雙引號擴(kuò)住的模塊,模塊中不可以出現(xiàn)雙引號。(言外之意:如果模塊中出現(xiàn)雙引號,則這個(gè)模塊要用雙引號將首尾擴(kuò)住)

“aaa”,bbbCRLF             合法
a"aa,bbbCRLF              不合法,因?yàn)閍"aa中包含了雙引號,而這個(gè)模塊沒有被雙引號擴(kuò)住

6.如果模塊中包含雙引號、半角逗號或換行符,則模塊首尾要用雙引號擴(kuò)住。

"a/r/na"a,bbbCRLF       合法,第一個(gè)模塊包含了換行符,要用雙引號包含
"a,aa",bbbCRLF            合法

7.當(dāng)雙引號出現(xiàn)在模塊中,要將模塊的首尾用雙引號擴(kuò)住,并且將模塊中的一個(gè)雙引號變成一對雙引號。

“a""aa”,bbbCRLF          合法,原始數(shù)據(jù)為a"aa,bbb

        有了以上規(guī)則,我們可以編寫出相應(yīng)的提取算法。以下是我在工作中編寫的一套從CSV文件中提取信息的核心代碼

BOOL CCSV2Json::Parse() {   BOOL bSuc = FALSE;   do {     if ( INVALID_HANDLE_VALUE == m_hFile ) {       break;     }     OVERLAPPED ov;     memset(&ov, 0, sizeof(OVERLAPPED));     BYTE lpBuffer[BUFFERSIZE] = {0};     DWORD dwHaveRead = 0;     std::string strSingle;     BOOL bFirstDoubleQuotes = FALSE;  // 第一個(gè)字符是否為"     BOOL bBeforeIsDoubleQuotes = FALSE;      BOOL bBeforeIsX0D = FALSE;     ListString Liststr;     BOOL bPairDoubleQuotes = FALSE;     while ( ReadFile(m_hFile, lpBuffer, sizeof(lpBuffer), &dwHaveRead, &ov ) ) {       ov.Offset += dwHaveRead;       for ( DWORD dwIndex = 0; dwIndex < dwHaveRead; dwIndex++ ) {         BYTE& by = *(lpBuffer + dwIndex);          if ( bFirstDoubleQuotes ) {           // 有前置"           if ( IsDoubleQuotes(by) ) {             bBeforeIsX0D = FALSE;             if ( bBeforeIsDoubleQuotes ) {               strSingle.append(1, (char)(by));               bBeforeIsDoubleQuotes = FALSE;             }             else {               bBeforeIsDoubleQuotes = TRUE;             }           }           else {             if ( bBeforeIsDoubleQuotes ) {               bFirstDoubleQuotes = FALSE;             }             bBeforeIsDoubleQuotes = FALSE;             if ( IsCRLF( by ) ){               if ( bFirstDoubleQuotes ) {                 strSingle.append(1, (char)(by));               }               else if (FALSE == bBeforeIsX0D) {                 Liststr.push_back(strSingle);                 m_Listliststr.push_back(Liststr);                 Liststr.clear();                 strSingle.clear();                 bFirstDoubleQuotes = FALSE;               }               bBeforeIsX0D = IsX0D(by);             }             else if ( IsSep(by) ) {               bBeforeIsX0D = FALSE;               if ( bFirstDoubleQuotes ) {                 strSingle.append(1, (char)(by));               }               else {                 bBeforeIsX0D = FALSE;                 Liststr.push_back(strSingle);                 strSingle.clear();               }             }             else {               bBeforeIsX0D = FALSE;               strSingle.append(1, (char)(by));             }           }         }         else{           // 如果無前置"           if ( IsDoubleQuotes(by) ) {             bBeforeIsX0D = FALSE;             if ( strSingle.empty() ) {               // 空串,第一個(gè)是"               bFirstDoubleQuotes = TRUE;               bBeforeIsDoubleQuotes = FALSE;             }             else {               strSingle.append(1,(char)(by));               continue;             }           }           else {             bBeforeIsDoubleQuotes = FALSE;             if ( IsCRLF( by ) ){               if (FALSE == bBeforeIsX0D) {                 Liststr.push_back(strSingle);                 m_Listliststr.push_back(Liststr);                 Liststr.clear();                 strSingle.clear();                 bFirstDoubleQuotes = FALSE;                 bBeforeIsDoubleQuotes = FALSE;               }               else {                 // 連續(xù)/r/n不考慮設(shè)置為新的行               }               bBeforeIsX0D = IsX0D(by);             }             else if ( IsSep(by) ) {               bBeforeIsX0D = FALSE;               Liststr.push_back(strSingle);               strSingle.clear();             }             else {               bBeforeIsX0D = FALSE;               strSingle.append(1, (char)(by));             }           }         }        }       memset(lpBuffer, 0, sizeof(lpBuffer));        }          if ( false == strSingle.empty() ) { //       while ( IsCRLF(strSingle.at(strSingle.length() - 1) ) && strSingle.length() > 0) { //         strSingle = strSingle.substr(0, strSingle.length() - 1 ); //       }       Liststr.push_back(strSingle);       m_Listliststr.push_back(Liststr);       Liststr.clear();       strSingle.clear();     }      bSuc = TRUE;   } while (0);      if ( NULL != m_hFile ) {     CloseHandle(m_hFile);     m_hFile = NULL;   }      return bSuc; } 

        這段代碼將CSV文件提取出來一個(gè)std::list<std::list<std::string>>結(jié)構(gòu)。如上面名字所示,我這個(gè)功能是要將CSV文件轉(zhuǎn)換為json格式,相應(yīng)的我也編寫了從json格式轉(zhuǎn)換為CSV格式文件的代碼。這些代碼都在工程中。

感謝閱讀,希望能幫助到大家,謝謝大家對本站的支持!

發(fā)表評論 共有條評論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表

圖片精選

主站蜘蛛池模板: 成人深夜福利视频 | 亚洲视频在线观看 | 极品少妇一区二区三区精品视频 | 亚洲最大av网站 | 老司机精品福利视频 | 国产精品久久久久久久久久免费 | 黄色免费观看 | 青青久在线视频 | 日本免费黄色网 | 成人福利在线观看 | 日本精品久久 | 欧美9999| 国产精久 | 欧美一级做a爰片免费视频 在线不卡日韩 | 成人久久久久爱 | 黄色的网站在线免费观看 | 久久99国产伦子精品免费 | h视频免费在线 | 黄色的网站在线 | 艹逼视频在线免费观看 | 亚洲三区视频 | 国产成人精品免费视频 | 日韩高清国产一区在线 | 九色av| h视频在线观看免费 | 欧美日韩国产精品久久久久 | 日本一区二区不卡视频 | 亚洲一区精品视频 | 亚洲综合精品 | 久久免费视频一区二区 | 久久亚洲国产视频 | 国产激情午夜 | 国产在线视频网站 | 欧美日韩国产在线观看 | 青青久在线视频免费观看 | 九一在线观看 | 国产美女高潮视频 | 亚洲码欧美码一区二区三区 | 欧美a在线 | 久久久国产精品入口麻豆 | 国产精品久久久久久久久免费 |