欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

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

 更新時間:2016年12月09日 15:30:33   投稿:lqh  
這篇文章主要介紹了標(biāo)準(zhǔn)CSV格式的介紹和分析以及解析算法實例詳解的相關(guān)資料,需要的朋友可以參考下

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

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

1.在不包含換行符(CRLF即 \r\n)的單條信息時,數(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.第一條信息可能是一個頭信息。這個頭信息和之后信息格式是相同的,并且和之后的信息有相同的模塊數(shù)(上例中,aaa和bbb和ccc和ddd各被視為一個模塊)。(個人認(rèn)為這是RFC設(shè)計這個CSV格式的一個缺陷,因為這個規(guī)則將無法讓我們從規(guī)則的角度去確認(rèn)第一條信息到底是頭信息還是普通信息。當(dāng)然RFC這么設(shè)計肯定有它的原因。)

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

1,aCRLF
2,bCRLF

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

4.每條信息都要使用半角逗號(,)分隔出若干模塊。每條信息的模塊數(shù)要相等。每條信息的最后一個模塊之后不可以使用半角逗號??崭穹灰暈橐粋€模塊的內(nèi)容而不可被忽略。(這條規(guī)則包含的信息量相對較多)

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

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

“aaa”,bbbCRLF             合法
a"aa,bbbCRLF              不合法,因為a"aa中包含了雙引號,而這個模塊沒有被雙引號擴住

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

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

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

“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;  // 第一個字符是否為" 
    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() ) { 
              // 空串,第一個是" 
              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文件提取出來一個std::list<std::list<std::string>>結(jié)構(gòu)。如上面名字所示,我這個功能是要將CSV文件轉(zhuǎn)換為json格式,相應(yīng)的我也編寫了從json格式轉(zhuǎn)換為CSV格式文件的代碼。這些代碼都在工程中。

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

相關(guān)文章

  • c++實現(xiàn)二叉查找樹示例

    c++實現(xiàn)二叉查找樹示例

    這篇文章主要介紹了c++實現(xiàn)二叉查找樹示例,實現(xiàn)二叉查找樹的基本功能,需要的朋友可以參考下
    2014-02-02
  • QML中動態(tài)與靜態(tài)模型應(yīng)用詳解

    QML中動態(tài)與靜態(tài)模型應(yīng)用詳解

    QML是一種描述性的腳本語言,文件格式以.qml結(jié)尾。語法格式非常像CSS(參考后文具體例子),但又支持javascript形式的編程控制。QtDesigner可以設(shè)計出·ui界面文件,但是不支持和Qt原生C++代碼的交互
    2022-08-08
  • 基于Qt實現(xiàn)簡易GIF播放器的示例代碼

    基于Qt實現(xiàn)簡易GIF播放器的示例代碼

    這篇文章主要介紹了如何利用Qt設(shè)計一個簡易GIF播放器,可以播放GIF動畫。其基本功能有載入文件、播放、暫停、停止、快進(jìn)和快退,感興趣的可以了解一下
    2022-06-06
  • C語言實現(xiàn)單鏈表逆序與逆序輸出實例

    C語言實現(xiàn)單鏈表逆序與逆序輸出實例

    這篇文章主要介紹了C語言實現(xiàn)單鏈表逆序與逆序輸出,是數(shù)據(jù)結(jié)構(gòu)與算法中比較基礎(chǔ)的重要內(nèi)容,有必要加以牢固掌握,需要的朋友可以參考下
    2014-08-08
  • OpenCV + MFC實現(xiàn)簡單人臉識別

    OpenCV + MFC實現(xiàn)簡單人臉識別

    這篇文章主要為大家詳細(xì)介紹了OpenCV + MFC實現(xiàn)簡單人臉識別,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2019-08-08
  • C語言實現(xiàn)班級學(xué)生管理系統(tǒng)

    C語言實現(xiàn)班級學(xué)生管理系統(tǒng)

    這篇文章主要為大家詳細(xì)介紹了C語言實現(xiàn)班級學(xué)生管理系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-11-11
  • VSCode搭建C/C++編譯環(huán)境的詳細(xì)教程

    VSCode搭建C/C++編譯環(huán)境的詳細(xì)教程

    Visual Studio Code是一款免費開源的現(xiàn)代化輕量級代碼編輯器,支持幾乎所有主流的開發(fā)語言的語法高亮、智能代碼補全、自定義熱鍵、括號匹配、代碼片段、代碼對比 Diff、GIT 等特性,這篇文章主要介紹了VSCode搭建C/C++編譯環(huán)境,需要的朋友可以參考下
    2020-05-05
  • C++指針與數(shù)組:指針詳解

    C++指針與數(shù)組:指針詳解

    本文從初學(xué)者的角度,深入淺出地講解C++中的指針、數(shù)組指針,對最?;煜囊脗鬟f、值傳遞和指針傳遞做了區(qū)處,需要的朋友可以參考下
    2021-09-09
  • 詳解Matlab繪制3D玫瑰花的方法(內(nèi)附旋轉(zhuǎn)版本)

    詳解Matlab繪制3D玫瑰花的方法(內(nèi)附旋轉(zhuǎn)版本)

    這篇文章主要為大家介紹了如何利用Matlab繪制3D版的玫瑰花以及旋轉(zhuǎn)版的3D玫瑰花,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以動手試一試
    2022-03-03
  • C語言中自動隱式轉(zhuǎn)換與類型強制轉(zhuǎn)換實例分析

    C語言中自動隱式轉(zhuǎn)換與類型強制轉(zhuǎn)換實例分析

    這篇文章主要介紹了C語言中自動隱式轉(zhuǎn)換與類型強制轉(zhuǎn)換實例分析,需要的朋友可以參考下
    2014-07-07

最新評論