haulm 发表于 2011-2-11 14:19:14

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

我发现分割 字符的确是件很了不起的工程。。。。
多个引号或分割符(,)还是会有些错误,还待进一步修正
QStringList DBBrowserDB::decodeCSV(const QString & csvfilename, char sep, char quote, int maxrecords, int * numfields)
{
QFile file(csvfilename);
QStringList curList;
bool inita = false;
bool initc = false;
int recs = 0;
*numfields = 0;

if(file.open(QIODevice::ReadOnly))
{
   QTextStream fin(&file);
   QString text_str,current;
   while(!fin.atEnd())
   {
   text_str=fin.readLine();
   int my_size,i_a=0;
   my_size=text_str.size();
   while(i_a<my_size)
   {

         if(text_str.at(i_a)==quote && inita==false)
         {
             inita=true;
         }
         if(text_str.at(i_a)==quote && inita==true)
         {
             if(i_a<my_size-1)
             {
             if(text_str.at(i_a+1)==sep)
               {
                  curList.append(current);
                  inita=false;
                  current.clear();
                }else
                  {
                  if(text_str.at(i_a+1)==quote)
                  {
                         current.append(text_str.at(i_a));
                         inita=false;
                         i_a++;
                  }

                }
            }

      }

         if(text_str.at(i_a)!=quote)
         {
            if(text_str.at(i_a)==sep && i_a>0)
            {
                if(text_str.at(i_a-1)==quote)
                {

                  if(current.size()!=0)
                  {
                  curList.append(current);
                  inita=false;
                  current.clear();
                  }

                }
                if(inita==false && current.size()>0)
                {
                  curList.append(current);
                  current.clear();
                }
                if(inita==true)
               {
                  current.append(sep);
                }
            }
            else
            {
            current.append(text_str.at(i_a));
            }
         }
         if(i_a==my_size-2 && text_str.at(i_a+1)==quote)
         {
             curList.append(current);
             inita=false;
             current.clear();
         }
         if(i_a==my_size-1 && text_str.at(i_a)!=quote)
         {
             curList.append(current);
             inita=false;
             current.clear();
         }
         qDebug()<<current;
         qDebug()<<curList;
   i_a++;
   }

   if(initc==false)
   {
         initc=true;
         *numfields=curList.count();
   }
   recs++;
   if(maxrecords==recs || maxrecords==*numfields)
   {break;}
   }

}
file.close();
   return curList;
   curList.clear();
}


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

zy_sunshine 发表于 2011-2-11 14:25:21

还是用python吧,哈哈,从来不烦恼
>>> ttt ="aa,bb,cc"
>>> ttt.split(',')
['aa', 'bb', 'cc']

nihui 发表于 2011-2-11 14:38:29

手写的 csv 分析器,最好有状态图表示吧,这个很难看懂的...

nihui 发表于 2011-2-11 14:39:40

另外就是 Qt 的 QString 有分割函数的
split()
section()
left()
mid()
right()

sejishikong 发表于 2011-2-11 16:07:02

QStrings的分割很好用啊。为什么要自己写啊。

haulm 发表于 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 发表 http://www.linuxfans.org/bbs/images/common/back.gif
另外就是 Qt 的 QString 有分割函数的
split()
section()
left()
mid()
right()
mid() splite() 有用过,遇到困难,最后只能是一个个字符老老实实分析,section() 没用过,left() right() 在这里不好用。

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

haulm 发表于 2011-2-11 21:55:35

看了一下 section() ,还是这个好用,这样的话我可以直接对文本分析后直接处理掉。

nihui 发表于 2011-2-11 22:49:24

https://github.com/nihui/oxygenspread/blob/master/file_csv.c

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

sejishikong 发表于 2011-2-12 09:43:56

原帖由 haulm 于 2011-2-11 21:43 发表 http://www.linuxfans.org/bbs/images/common/back.gif
几位兄台,如果能直接用 splite 分割就不用想破头了。。。
我要实现的是 excel 对 CSV 文件的分析,CSV 文件的分割遇到特殊文本会用引号区分再用逗号隔开,但是遇到正常文本的表格就直接用逗号隔开。
这里就出现了“xxx”, ...
只要c能处理,qstrings肯定能处理,再说qt还有qregexp,肯定比c要方便的。

haulm 发表于 2011-2-12 10:44:00

原帖由 sejishikong 于 2011-2-12 09:43 发表 http://www.linuxfans.org/bbs/images/common/back.gif

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

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

sejishikong 发表于 2011-2-12 11:44:05

一个参考:http://sourceforge.net/projects/qcsv/
我没仔细看,不过大体思路这个就行,顶多是regexp需要调整。

nihui 发表于 2011-2-12 11:51:24

以下定义译自 wikipedia 上的 CSV 篇目


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

haulm 发表于 2011-2-12 12:04:52

我的分析器遇到内容有,号,有时会出错,正在下载那个项目看看。

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

haulm 发表于 2011-2-12 12:18:06

原帖由 nihui 于 2011-2-12 11:51 发表 http://www.linuxfans.org/bbs/images/common/back.gif
以下定义译自 wikipedia 上的 CSV 篇目


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

nihui 发表于 2011-2-12 14:32:18

原帖由 haulm 于 2011-2-12 12:18 发表 http://www.linuxfans.org/bbs/images/common/back.gif

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

给个分析器的流程,这样应该不难了。

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 编辑 ]
页: [1] 2
查看完整版本: 有能力补充修正的请进,这几天脑子乱的。。。。