• linkedu视频
  • 平面设计
  • 电脑入门
  • 操作系统
  • 办公应用
  • 电脑硬件
  • 动画设计
  • 3D设计
  • 网页设计
  • CAD设计
  • 影音处理
  • 数据库
  • 程序设计
  • 认证考试
  • 信息管理
  • 信息安全
菜单
linkedu.com
  • 网页制作
  • 数据库
  • 程序设计
  • 操作系统
  • CMS教程
  • 游戏攻略
  • 脚本语言
  • 平面设计
  • 软件教程
  • 网络安全
  • 电脑知识
  • 服务器
  • 视频教程
  • JavaScript
  • ASP.NET
  • PHP
  • 正则表达式
  • AJAX
  • JSP
  • ASP
  • Flex
  • XML
  • 编程技巧
  • Android
  • swift
  • C#教程
  • vb
  • vb.net
  • C语言
  • Java
  • Delphi
  • 易语言
  • vc/mfc
  • 嵌入式开发
  • 游戏开发
  • ios
  • 编程问答
  • 汇编语言
  • 微信小程序
  • 数据结构
  • OpenGL
  • 架构设计
  • qt
  • 微信公众号
您的位置:首页 > 程序设计 >C语言 > 标准CSV格式的介绍和分析以及解析算法实例详解

标准CSV格式的介绍和分析以及解析算法实例详解

作者: 字体:[增加 减小] 来源:互联网 时间:2017-05-28

通过本文主要向大家介绍了csv德国牧羊犬标准,csv德牧标准,csv标准,csv标准格式,csv德国牧羊犬俱乐部等相关知识,希望对您有所帮助,也希望大家支持linkedu.com www.linkedu.com

     CSV是一种古老的数据传输格式,它的全称是Comma-Separated Values(逗号分隔值)。出生在那个标准缺失的蛮荒年代,CSV的标准一直(到2005年)是NULL——世间存在着N种CSV格式,它们自成体系,相互不兼容。比如我们从名字可以认为CSV至少是一种使用逗号分隔的格式,但是实际上,有的CSV格式却是使用分号(;)去做分隔。假如,不存在一种标准,那么这东西最终会因为碎片化而发展缓慢,甚至没落。本文讨论的CSV格式是基于2005年发布的RFC4180规范。我想,在这个规范发布之后,大家应该会更加自觉的遵从这套规范去开发——虽然这套标准依旧存在着一些致命的缺陷

        我们可以从IETF上获得包含了CSV格式定义的文档。当然,如果你觉得看英文文档麻烦,你可以直接看我的下文。

1.在不包含换行符(CRLF即 \r\n)的单条信息时,数据要保持在一行,并且使用\r\n结束。

aaa,bbb,ccc,dddCRLF   合法

aaa,b                            内容中无换行符,而单条信息被换行,不合法

bb.ccc,dddCRLF

2.最后一条信息可以没有换行符(当然有换行符也是合法的)

aaa,bbb,ccc,dddCRLF

eee,fff,ggg,hhh           合法

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

3.第一条信息可能是一个头信息。这个头信息和之后信息格式是相同的,并且和之后的信息有相同的模块数(上例中,aaa和bbb和ccc和ddd各被视为一个模块)。(个人认为这是RFC设计这个CSV格式的一个缺陷,因为这个规则将无法让我们从规则的角度去确认第一条信息到底是头信息还是普通信息。当然RFC这么设计肯定有它的原因。)

index,character          合法,从字面意思上我们可以认为这个是头,当然我们也可以认为它不是头

1,aCRLF
2,bCRLF

indexCRLF                 非法,模块数不统一
1,aCRLF

4.每条信息都要使用半角逗号(,)分隔出若干模块。每条信息的模块数要相等。每条信息的最后一个模块之后不可以使用半角逗号。空格符被视为一个模块的内容而不可被忽略。(这条规则包含的信息量相对较多)

aaa,bbbCRLF                合法
ccc,ddd,CRLF                非法,一条信息的最后一个模块不可以使用半角逗号
eee;ffffCRLF                   非法,要使用半角逗号分隔,而不是分号
ggg,       h h h  CRLF     合法,注意hhh模块的若干个空格,它属于模块内容而不可以被忽略
iii,jjj,kkkkCRLF               非法,模块数和上面不统一

5.每个模块首尾可以使用双引号扩住(当然也可以不使用)。如果不使用双引号扩住的模块,模块中不可以出现双引号。(言外之意:如果模块中出现双引号,则这个模块要用双引号将首尾扩住)

“aaa”,bbbCRLF             合法
a"aa,bbbCRLF              不合法,因为a"aa中包含了双引号,而这个模块没有被双引号扩住

6.如果模块中包含双引号、半角逗号或换行符,则模块首尾要用双引号扩住。

"a\r\na"a,bbbCRLF       合法,第一个模块包含了换行符,要用双引号包含
"a,aa",bbbCRLF            合法

7.当双引号出现在模块中,要将模块的首尾用双引号扩住,并且将模块中的一个双引号变成一对双引号。

“a""aa”,bbbCRLF          合法,原始数据为a"aa,bbb

        有了以上规则,我们可以编写出相应的提取算法。以下是我在工作中编写的一套从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 { 
                // 连续\r\n不考虑设置为新的行 
              } 
              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) 



 
分享到:QQ空间新浪微博腾讯微博微信百度贴吧QQ好友复制网址打印

您可能想查找下面的文章:

  • 标准CSV格式的介绍和分析以及解析算法实例详解

相关文章

  • 2017-05-28C++中函数的默认参数详细解析
  • 2017-05-28详解C++编程中运算符的使用
  • 2017-05-28二分法求多项式在-10 10间值的实现代码
  • 2017-05-28浅析直接插入排序与折半插入排序
  • 2017-05-28关于C++中0是十进制还是八进制的问题
  • 2017-05-28C++卸载程序功能示例
  • 2017-05-28VC创建进程CreateProcess的方法
  • 2017-05-28用C语言的泛型实现交换两个变量值
  • 2017-05-28window调用api列出当前所有进程示例
  • 2017-08-17可变参数函数

文章分类

  • JavaScript
  • ASP.NET
  • PHP
  • 正则表达式
  • AJAX
  • JSP
  • ASP
  • Flex
  • XML
  • 编程技巧
  • Android
  • swift
  • C#教程
  • vb
  • vb.net
  • C语言
  • Java
  • Delphi
  • 易语言
  • vc/mfc
  • 嵌入式开发
  • 游戏开发
  • ios
  • 编程问答
  • 汇编语言
  • 微信小程序
  • 数据结构
  • OpenGL
  • 架构设计
  • qt
  • 微信公众号

最近更新的内容

    • C++设计模式之原型模式
    • C基础 mariadb处理的简单实例
    • C++利用链栈实现表达式求值
    • Visual C++中Tab View的多种实现方法
    • C++11右值引用和std::move语句实例解析(推荐)
    • CISBitmap派生的VC++位图透明类实例
    • C++循环队列实现模型
    • 如何通过函数指针调用函数(实现代码)
    • 解析C语言与C++的编译模型
    • C++ STL list 遍历删除出错解决方案

关于我们 - 联系我们 - 免责声明 - 网站地图

©2020-2025 All Rights Reserved. linkedu.com 版权所有