CSV檔案處理
阿新 • • 發佈:2021-08-04
目錄
2.2 寫CSV檔案
1. CSV檔案簡單介紹
CSV,Comma-Separated Values,翻譯過來就是逗號分隔值,也可以稱為符號分隔值,因為也可以不是逗號分隔的。CSV檔案的內容是以逗號分隔開的一系列資料。CSV檔案可用Excel和記事本開啟。
工作中用到CSV檔案無非是讀和寫CSV檔案 ,接下來是關於CSV檔案讀和寫的操作。
2. CSV檔案的讀寫操作
讀CSV檔案可以按照讀TXT檔案去讀,寫CSV檔案時需要注意要確保當前檔案的位置是在最後一行。
2.1 讀CSV檔案
有的CSV檔案是有標題行的,如下。通常是讀取需要的內容,標題行捨棄掉。
2.1.1 C讀取CSV檔案
使用C讀取CSV檔案需要用到fseek()函式,該函式原型為fseek(FILE* stream,long offset,int fromwhere);
引數fromwhere表示從什麼地方開始,取值有三個,分別是:
設定值 | 備註 |
SEEK_SET=0 | 表示從檔案開頭 |
SEEK_CUR=1 | 表示從檔案當前位置 |
SEEK_END=2 | 表示從檔案末尾 |
#include <stdio.h>
bool ReadCSV(const char* filename) { FILE *fp = nullptr; char *line, *record; char buffer[1024]; if ((fp = fopen(filename, "at+")) != nullptr) { line = fgets(buffer, sizeof(buffer), fp); // 1. 獲取第一行的內容 fseek(fp, strlen(line), SEEK_SET); // 2. 定位到第二行 while ((line = fgets(buffer, sizeof(buffer), fp)) != nullptr)// 3. 逐行獲取檔案內容 { record = strtok(line, ","); while ((record = strtok(line, ",")) != nullptr)// 4. 分隔每一行的每一個數據 printf("%s ", record);// 5. 列印每一行的每一個數據,以空格隔開 printf("\n"); } fclose(fp); fp = nullptr; return true; } else { printf("Open file fail!"); return false; } }
2.1.2 C++讀取CSV檔案
使用fstream檔案流讀取CSV檔案。
使用正則表示式匹配每個單元格的內容,需要新增標頭檔案#include <regex>,
bool ReadCSV_CPP(const std::string& filename) { std::fstream file(filename,std::ios::in); // 1. 開啟檔案 if(!file.is_open()) { std::string exp_string = "Open File FAIL!"; throw exp_string; } std::string strline; std::smatch sm; std::regex rx("(\\w+)"); //CSV檔案每個單元格的格式,此處匹配的是字母、數字、下劃線 std::string strtemp; while (std::getline(file,strline)) { // 2. 逐行讀取csv檔案 while (std::regex_search(strline, sm, rx)) // 3. 正則表示式匹配每個單元格的內容 { strtemp = sm.begin()->str(); // 4. 匹配到的單元格內的內容 strline = sm.suffix().str(); // 5. 剩下的字元 printf("%s ",strtemp.c_str()); } if(!strline.empty()) { strtemp = strline; printf("%s ",strtemp.c_str()); } printf("\n"); } file.close(); return true; }
2.1.3 QT讀取CSV檔案
bool ReadCSV_Qt(const QString& filename) { QFile file(filename); if(!file.open(QFile::ReadOnly | QFile::Text)) { std::string s ="read file fail"; throw s; } QStringList content; // 所有逗號分隔的內容 content.clear(); QTextStream text(&file); QStringList listContent; //每行的內容 while (!text.atEnd()) { listContent.push_back(text.readLine()); // 逐行獲取每行內容 } for(QString& str:listContent) { content.push_back(str.split(",")); // 獲取每行的逗號分隔開的內容 } file.close(); return true; }
2.2 寫CSV檔案
寫CSV檔案時需要注意當前檔案指標位置在檔案的最後一行的開始位置。
2.2.1 C寫CSV檔案
同樣的,C寫CSV檔案時也會用到fseek()函式,此時fromwhere引數需要設定為SEEK_END,表示檔案指標定位到檔案末尾。
// data資料型別可以任意為需要儲存的內容 bool WriteCSV_C(const char* filename,const char* data) { FILE *pf = nullptr; pf = std::freopen(filename, "at", stdout); // freopen()函式用於檔案流重定向 if (nullptr == pf) { const char* chErrmsg = "Open File FAIL!"; throw chErrmsg; } long longfileSizeTemp = ftell(pf); // 獲取當前檔案大小 size_t datasize = strlen(data); fseek(pf, 0, SEEK_END); //將檔案指標定位到檔案末尾 longfileSizeTemp = ftell(pf); if (0 == longfileSizeTemp) // 若檔案大小=0表示該檔案還未寫入資料 { for(int i=0;i<datasize;i++) { printf("col_%d,",i);// 輸入csv的標題內容 } } printf("\n"); for(int i=0;i<datasize;i++) { printf("%c,",data[i]);// 輸入csv的資料內容 } fclose(pf); pf = nullptr; return true; }
2.2.2 C++寫CSV檔案
使用fstream類寫CSV檔案,需要使用到seekp()、tellp()獲取到檔案是否為空。
bool WriteCSV_CPP(const std::string& filename,const std::vector<int>& data) { std::fstream file(filename,std::ios::out|std::ios::app); // 1. 開啟檔案,ios::app表示在檔案尾追加,如果不加該屬性,那麼每次寫的時候會覆蓋檔案內容 if(!file.is_open()) { std::string exp_string = "Open File FAIL!"; throw exp_string; } // 以下兩行獲取檔案的大小,首先設定檔案流指標位置為末尾,然後返回當前檔案寫指標的位置,如果為0表示該檔案為空 file.seekp(0,file.end); // seekp()函式設定輸出檔案流的檔案流指標位置 size_t filesize = file.tellp(); // 返回檔案寫指標的位置 int iDataSize = data.size(); if(0 == filesize) { for(int i=0;i<iDataSize;++i) // 如果檔案為空,新增標題 { file << "col_" << i << ","; } } file << std::endl; for(int i=0;i<iDataSize;++i) // 寫入內容 { file << data.at(i) << ","; } file.close(); return true; }
2.2.3 Qt寫CSV檔案
bool WriteCSV_Qt(const QString& filename,const QStringList& data) { QFile file(filename); if(!file.open(QFile::WriteOnly | QFile::Text | QFile::Append)) // 1. 以追加方式開啟檔案 { std::string s ="Open File FAIL"; throw s; } qint64 filesize = file.size(); // 獲取檔案大小 int iDataSize = data.size(); if(0 == filesize) { QString strTemp; for(int i=0;i<iDataSize;++i) //檔案為空時,填入標題 { strTemp.sprintf("col_%d,",i); file.write(strTemp.toStdString().c_str()); } } file.write("\n"); for(QString str:data) { file.write(str.toStdString().c_str()); // 寫入檔案內容 file.write(","); } file.close(); return true; }