QQ登录

只需一步,快速开始

 找回密码
 注册

QQ登录

只需一步,快速开始

查看: 3169|回复: 18

有能力补充修正的请进,这几天脑子乱的。。。。

[复制链接]
发表于 2011-2-11 14:19:14 | 显示全部楼层 |阅读模式
我发现分割 字符的确是件很了不起的工程。。。。
多个引号或分割符(,)还是会有些错误,还待进一步修正

  1. QStringList DBBrowserDB::decodeCSV(const QString & csvfilename, char sep, char quote, int maxrecords, int * numfields)
  2. {
  3. QFile file(csvfilename);
  4. QStringList curList;
  5. bool inita = false;
  6. bool initc = false;
  7. int recs = 0;
  8. *numfields = 0;

  9. if(file.open(QIODevice::ReadOnly))
  10. {
  11.      QTextStream fin(&file);
  12.      QString text_str,current;
  13.      while(!fin.atEnd())
  14.      {
  15.      text_str=fin.readLine();
  16.      int my_size,i_a=0;
  17.      my_size=text_str.size();
  18.      while(i_a<my_size)
  19.      {

  20.          if(text_str.at(i_a)==quote && inita==false)
  21.          {
  22.              inita=true;
  23.          }
  24.          if(text_str.at(i_a)==quote && inita==true)
  25.          {
  26.              if(i_a<my_size-1)
  27.              {
  28.              if(text_str.at(i_a+1)==sep)
  29.                  {
  30.                     curList.append(current);
  31.                     inita=false;
  32.                     current.clear();
  33.                 }else
  34.                     {
  35.                     if(text_str.at(i_a+1)==quote)
  36.                     {
  37.                          current.append(text_str.at(i_a));
  38.                          inita=false;
  39.                          i_a++;
  40.                     }

  41.                 }
  42.             }

  43.         }

  44.          if(text_str.at(i_a)!=quote)
  45.          {
  46.             if(text_str.at(i_a)==sep && i_a>0)
  47.             {
  48.                 if(text_str.at(i_a-1)==quote)
  49.                 {

  50.                     if(current.size()!=0)
  51.                     {
  52.                     curList.append(current);
  53.                     inita=false;
  54.                     current.clear();
  55.                     }

  56.                 }
  57.                 if(inita==false && current.size()>0)
  58.                 {
  59.                     curList.append(current);
  60.                     current.clear();
  61.                 }
  62.                 if(inita==true)
  63.                {
  64.                     current.append(sep);
  65.                 }
  66.             }
  67.             else
  68.             {
  69.             current.append(text_str.at(i_a));
  70.             }
  71.          }
  72.          if(i_a==my_size-2 && text_str.at(i_a+1)==quote)
  73.          {
  74.              curList.append(current);
  75.              inita=false;
  76.              current.clear();
  77.          }
  78.          if(i_a==my_size-1 && text_str.at(i_a)!=quote)
  79.          {
  80.              curList.append(current);
  81.              inita=false;
  82.              current.clear();
  83.          }
  84.          qDebug()<<current;
  85.          qDebug()<<curList;
  86.      i_a++;
  87.      }

  88.      if(initc==false)
  89.      {
  90.          initc=true;
  91.          *numfields=curList.count();
  92.      }
  93.      recs++;
  94.      if(maxrecords==recs || maxrecords==*numfields)
  95.      {break;}
  96.      }

  97. }
  98.   file.close();
  99.    return curList;
  100.    curList.clear();
  101. }
复制代码

[ 本帖最后由 haulm 于 2011-2-12 10:45 编辑 ]
发表于 2011-2-11 14:25:21 | 显示全部楼层
还是用python吧,哈哈,从来不烦恼
>>> ttt ="aa,bb,cc"
>>> ttt.split(',')
['aa', 'bb', 'cc']
回复

使用道具 举报

发表于 2011-2-11 14:38:29 | 显示全部楼层
手写的 csv 分析器,最好有状态图表示吧,这个很难看懂的...
回复

使用道具 举报

发表于 2011-2-11 14:39:40 | 显示全部楼层
另外就是 Qt 的 QString 有分割函数的
split()
section()
left()
mid()
right()
回复

使用道具 举报

发表于 2011-2-11 16:07:02 | 显示全部楼层
QStrings的分割很好用啊。为什么要自己写啊。
回复

使用道具 举报

 楼主| 发表于 2011-2-11 21:43:33 | 显示全部楼层
几位兄台,如果能直接用 splite 分割就不用想破头了。。。
我要实现的是 excel 对 CSV 文件的分析,CSV 文件的分割遇到特殊文本会用引号区分再用逗号隔开,但是遇到正常文本的表格就直接用逗号隔开。
这里就出现了“xxx”,"""""",",,,"等。。。
如果直接用 splite 分割你觉得能得到什么正确的结果?
比如一个 CSV 数字描述
1,000 1,000,这个存成 CVS( 逗号) 就出是 1“,”000,1","000
那你直接用 splite怎么分割?
原帖由 nihui 于 2011-2-11 14:39 发表
另外就是 Qt 的 QString 有分割函数的
split()
section()
left()
mid()
right()

mid() splite() 有用过,遇到困难,最后只能是一个个字符老老实实分析,section() 没用过,left() right() 在这里不好用。

[ 本帖最后由 haulm 于 2011-2-11 21:51 编辑 ]
回复

使用道具 举报

 楼主| 发表于 2011-2-11 21:55:35 | 显示全部楼层
看了一下 section() ,还是这个好用,这样的话我可以直接对文本分析后直接处理掉。
回复

使用道具 举报

发表于 2011-2-11 22:49:24 | 显示全部楼层
https://github.com/nihui/oxygenspread/blob/master/file_csv.c

以前学win32编程做的表格,纯C的,但愿你能看懂吧。。
回复

使用道具 举报

发表于 2011-2-12 09:43:56 | 显示全部楼层
原帖由 haulm 于 2011-2-11 21:43 发表
几位兄台,如果能直接用 splite 分割就不用想破头了。。。
我要实现的是 excel 对 CSV 文件的分析,CSV 文件的分割遇到特殊文本会用引号区分再用逗号隔开,但是遇到正常文本的表格就直接用逗号隔开。
这里就出现了“xxx”, ...

只要c能处理,qstrings肯定能处理,再说qt还有qregexp,肯定比c要方便的。
回复

使用道具 举报

 楼主| 发表于 2011-2-12 10:44:00 | 显示全部楼层
原帖由 sejishikong 于 2011-2-12 09:43 发表

只要c能处理,qstrings肯定能处理,再说qt还有qregexp,肯定比c要方便的。

我也都写好了,只不过有时出现段错误,比如遇到重复的一堆引号和逗号相加杂的,qDebug 分析不到什么,更麻烦的是
不知道 office 为何在处理 CVS   ",     这两个左可相连的符号时用了更多的引号?
这种程序看似简单,实际上没法把这种简单的抽象任务一下就写成程序,只能一点点调试和分析错误。
用 QString 的原因是因为可以按编码进行分析,用 char * 就遇到半字问题了。
本来想写注解的,后来发现没完成之前,注解都没法写清楚。

[ 本帖最后由 haulm 于 2011-2-12 10:48 编辑 ]
回复

使用道具 举报

发表于 2011-2-12 11:44:05 | 显示全部楼层
一个参考:http://sourceforge.net/projects/qcsv/
我没仔细看,不过大体思路这个就行,顶多是regexp需要调整。
回复

使用道具 举报

发表于 2011-2-12 11:51:24 | 显示全部楼层
以下定义译自 wikipedia 上的 CSV 篇目

每行记录由 \n 或者 \r\n 分隔,但是字段内嵌的 \n 或 \r\n 不算
每条字段由 , 分隔
如果字段中内嵌 , ,需要使用 " 括起这条字段
如果字段中内嵌 \n 或 \r\n ,需要使用 " 括起这条字段
如果字段中内嵌 " ,需要在该 " 前面再添加 " 转义
字段前后的空白需要保留
如果字段中没有内嵌 , 或 \n 或 \r\n 或 ",可以使用 " 括起这条字段,也可以不使用
第一行记录可能包含字段的属性名称
回复

使用道具 举报

 楼主| 发表于 2011-2-12 12:04:52 | 显示全部楼层
我的分析器遇到内容有,号,有时会出错,正在下载那个项目看看。

[ 本帖最后由 haulm 于 2011-2-12 12:14 编辑 ]

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?注册

×
回复

使用道具 举报

 楼主| 发表于 2011-2-12 12:18:06 | 显示全部楼层
原帖由 nihui 于 2011-2-12 11:51 发表
以下定义译自 wikipedia 上的 CSV 篇目


实现起来就没有描述的那么简单了。
回复

使用道具 举报

发表于 2011-2-12 14:32:18 | 显示全部楼层
原帖由 haulm 于 2011-2-12 12:18 发表

实现起来就没有描述的那么简单了。


给个分析器的流程,这样应该不难了。
dq表示双引号,sep表示分隔符逗号,lf表示换行和回车
stateA: closed-dq
stateB: opening-dq
stateC: opening-dq+dq(?) / closed-dq

初始stateA
读入字符c,直到eof
    c为dq
        stateA: -> stateB
        stateB: -> stateC
        stateC: dq 存入 field,-> stateA
    c为sep
        stateA/C: field 存入 record,-> stateA
        stateB: sep 存入 field
    c为lf
        stateA/C: field 存入 record,record 存入 table,-> stateA
        stateB: lf 存入 field
    其它
        stateA/C: c 存入 field,-> stateA
        stateB: c 存入 field

[ 本帖最后由 nihui 于 2011-2-12 14:37 编辑 ]
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

GMT+8, 2024-11-2 06:31 , Processed in 0.047531 second(s), 16 queries .

© 2021 Powered by Discuz! X3.5.

快速回复 返回顶部 返回列表