Qt解析CSV文件

最近需要解析Excel文件,于是顺带写了解析CSV的代码

定义数据类型LX::Sheet

 1 #ifndef LX_H
 2 #define LX_H
 3 
 4 #include <QString>
 5 #include <QStringList>
 6 
 7 namespace LX
 8 {
 9 class Sheet
10 {
11     enum FieldType{STRING, INT, DOUBLE, BOOL};
12 public:
13     Sheet(){}
14     Sheet(Sheet&& rhs);
15     Sheet &operator =(Sheet &&rhs);
16 public:
17     QString name;
18     QList<QStringList> data;
19     QList<FieldType> fieldTypes;
20 };
21 }
22 
23 #endif // LX_H
//解析CSV文件
1
LX::Sheet FileParse::parseCSV(const QString &fileName) 2 { 3 LX::Sheet sheet; 4 5 int nameStartIndex = fileName.lastIndexOf('/') + 1; 6 if(nameStartIndex < 1) 7 { 8 nameStartIndex = fileName.lastIndexOf('\') + 1; 9 } 10 int nameEndIndex = fileName.lastIndexOf('.'); 11 sheet.name = fileName.mid(nameStartIndex, nameEndIndex - nameStartIndex); 12 13 QFile file(fileName); 14 if(!file.open(QIODevice::ReadOnly | QIODevice::Text)) 15 { 16 return sheet; 17 } 18 19 QTextStream inStream(&file); 20 21 for( QString lineStr; !inStream.atEnd(); ) 22 { 23 lineStr = inStream.readLine(); 24 if(lineStr.isEmpty()) 25 { 26 continue; 27 } 28 29 sheet.data.append(splitCSVLine(lineStr)); 30 } 31 32 return qMove(sheet); 33 } 34 35 QStringList FileParse::splitCSVLine(const QString &lineStr) 36 { 37 QStringList strList; 38 QString str; 39 40 int length = lineStr.length(); 41 int quoteCount = 0; 42 int repeatQuoteCount = 0; 43 44 for(int i = 0; i < length; ++i) 45 { 46 if(lineStr[i] != '"') 47 { 48 repeatQuoteCount = 0; 49 if(lineStr[i] != ',') 50 { 51 str.append(lineStr[i]); 52 } 53 else 54 { 55 if(quoteCount % 2) 56 { 57 str.append(','); 58 } 59 else 60 { 61 strList.append(str); 62 quoteCount = 0; 63 str.clear(); 64 } 65 } 66 } 67 else 68 { 69 ++quoteCount; 70 ++repeatQuoteCount; 71 if(repeatQuoteCount == 4) 72 { 73 str.append('"'); 74 repeatQuoteCount = 0; 75 quoteCount -= 4; 76 } 77 } 78 } 79 strList.append(str); 80 81 return qMove(strList); 82 }

生成CSV文件

 1 bool FileParse::generateCSV(const QString &fileName, const LX::Sheet &sheet)
 2 {
 3     QFile file(fileName);
 4     bool openOk = file.open(QIODevice::WriteOnly);
 5     if(!openOk)
 6     {
 7         return false;
 8     }
 9     QTextStream outStream(&file);
10 
11     int strCount = sheet.data.count();
12     for(int i = 0; i < strCount; ++i)
13     {
14         outStream << joinCSVStrs(sheet.data.at(i));
15         outStream << '
';
16     }
17 
18     return true;
19 }
 1 QString FileParse::joinCSVStrs(const QStringList &strList)
 2 {
 3     QString lineStr;
 4 
 5     int strCount = strList.count();
 6     int lastStrIndex = strCount - 1;
 7 
 8     for(int k = 0; k < strCount; ++k)
 9     {
10         QString tarStr;
11         bool commaFlag = false;
12 
13         const QString& oriStr = strList.at(k);
14         int length = oriStr.length();
15         for(int i = 0; i < length; ++i)
16         {
17             if(oriStr[i] == ',')
18             {
19                 tarStr.append(oriStr[i]);
20                 commaFlag = true;
21             }
22             else if(oriStr[i] == '"')
23             {
24                 tarStr.append("""""");
25             }
26             else
27             {
28                 tarStr.append(oriStr[i]);
29             }
30         }
31         if(commaFlag)
32         {
33             tarStr.push_front('"');
34             tarStr.push_back('"');
35         }
36         if(k != lastStrIndex)
37         {
38             tarStr.append(',');
39         }
40 
41         lineStr.append(tarStr);
42     }
43 
44     return qMove(lineStr);
45 }

解析规则为:

1、若逗号间无数据,仍解释为空数据

2、若字段中含有逗号则用"将字段包含起来

3、若数据中存在 " ,则将其替换为 """"

转自:http://www.cnblogs.com/lixtary/p/4252586.html

原文地址:https://www.cnblogs.com/lpxblog/p/6049074.html