Qt讀寫CSV文件的三種方式及優(yōu)劣對比
前言
作為一種常見的數(shù)據(jù)交換格式,CSV(Comma Separated Values)文件常常用于數(shù)據(jù)導(dǎo)出和導(dǎo)入等場合。在實(shí)際開發(fā)中,我們也需要使用Qt來實(shí)現(xiàn)CSV文件的讀寫操作。本篇博客將介紹使用Qt實(shí)現(xiàn)CSV讀寫的方法,并分析每種實(shí)現(xiàn)方式的優(yōu)缺點(diǎn)。
一、使用QStringList及QTextStream實(shí)現(xiàn)CSV文件讀寫
本方法使用QStringList來保存每行數(shù)據(jù),使用QTextStream類讀寫文本文件。具體實(shí)現(xiàn)代碼如下:
// 讀取CSV文件
bool readCsv(QString filePath, QList<QStringList>& data)
{
QFile file(filePath);
if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
return false;
QTextStream stream(&file);
while (!stream.atEnd())
{
QString line = stream.readLine();
QStringList row = line.split(',', Qt::SkipEmptyParts);
data.append(row);
}
file.close();
return true;
}
// 寫入CSV文件
bool writeCsv(QString filePath, QList<QStringList>& data)
{
QFile file(filePath);
if (!file.open(QIODevice::WriteOnly | QIODevice::Text))
return false;
QTextStream stream(&file);
for (int i = 0; i < data.size(); i++)
{
QStringList row = data.at(i);
for (int j = 0; j < row.size(); j++)
{
stream << row.at(j);
if (j < row.size() - 1)
stream << ",";
}
stream << "\n";
}
file.close();
return true;
}
該示例代碼運(yùn)用了QTextStream的readLine()和<<運(yùn)算符來實(shí)現(xiàn)CSV文件數(shù)據(jù)的讀寫。需要注意的是,在讀取CSV文件時(shí),要使用QStringList的split()函數(shù)來將每行拆分為多個(gè)字符串,并用字符串列表保存。在寫入CSV文件時(shí),要使用QStringList的join()函數(shù)來將每行數(shù)據(jù)轉(zhuǎn)為字符串,并用逗號(hào)分隔,產(chǎn)生一條CSV行,最后一行不應(yīng)該有逗號(hào)。
優(yōu)點(diǎn):
- 實(shí)現(xiàn)簡單:使用QStringList和QTextStream實(shí)現(xiàn)CSV讀寫操作非常簡單,能夠快速上手;
- 代碼量少:相對其他實(shí)現(xiàn)方式,該方法實(shí)現(xiàn)的代碼量較少。
缺點(diǎn):
- 寫入數(shù)據(jù)順序不能改變:當(dāng)數(shù)據(jù)量大的時(shí)候,使用該方法逐行寫入文件,文件I/O開銷相對較大,導(dǎo)致寫入速度變慢。同時(shí),該實(shí)現(xiàn)方式要求數(shù)據(jù)順序不能改變,因?yàn)槊啃袛?shù)據(jù)只存儲(chǔ)在單獨(dú)的QStringList中。
二、使用QTextCodec及QByteArray實(shí)現(xiàn)CSV文件讀寫
本方法使用QTextCodec來處理編碼問題,并使用QByteArray來讀寫文件。具體實(shí)現(xiàn)如下:
// 讀取CSV文件
bool readCsv(QString filePath, QList<QStringList>& data)
{
QFile file(filePath);
if (!file.open(QIODevice::ReadOnly))
return false;
QTextCodec* codec = QTextCodec::codecForName("UTF-8"); // 使用UTF-8編碼
QByteArray content = file.readAll();
QString text = codec->toUnicode(content);
QStringList lines = text.split('\n');
for (int i = 0; i < lines.size(); i++)
{
if (!lines.at(i).isEmpty())
{
QStringList row = lines.at(i).split(',');
data.append(row);
}
}
file.close();
return true;
}
// 寫入CSV文件
bool writeCsv(QString filePath, QList<QStringList>& data)
{
QFile file(filePath);
if (!file.open(QIODevice::WriteOnly))
return false;
QTextCodec* codec = QTextCodec::codecForName("UTF-8"); // 使用UTF-8編碼
for (int i = 0; i < data.size(); i++)
{
QStringList row = data.at(i);
QString line = row.join(",");
line += "\n";
QByteArray encodedLine = codec->fromUnicode(line);
file.write(encodedLine);
}
file.close();
return true;
}
該示例代碼在讀取CSV文件時(shí)使用了QTextCodec的codecForName()方法來指定文件編碼為UTF-8,使用QByteArray類保存文件數(shù)據(jù),通過QTextCodec::toUnicode()函數(shù)將字節(jié)數(shù)組轉(zhuǎn)換成QString對象。在寫入CSV文件時(shí),使用QByteArray類保存每行數(shù)據(jù),并將數(shù)據(jù)編碼成字節(jié)數(shù)組后寫入文件。
優(yōu)點(diǎn):
- 適用性廣泛:該實(shí)現(xiàn)方式適用性廣泛,可以處理各種不同的字符編碼;
- 寫入速度快:使用QByteArray類來讀寫文件,文件I/O開銷相對較少。
缺點(diǎn):
- 實(shí)現(xiàn)復(fù)雜:相對于第一種實(shí)現(xiàn)方式,該方法需要處理編碼問題和字節(jié)流轉(zhuǎn)換問題,因此實(shí)現(xiàn)方式相對復(fù)雜一些。
三、使用QStandardItemModel實(shí)現(xiàn)CSV文件讀寫
本方法使用QStandardItemModel來保存每行數(shù)據(jù),并使用QTextStream來讀寫文件。具體實(shí)現(xiàn)如下:
// 讀取CSV文件
bool readCsv(QString filePath, QStandardItemModel* model)
{
QFile file(filePath);
if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
return false;
QTextStream stream(&file);
while (!stream.atEnd())
{
QString line = stream.readLine();
QStringList row = line.split(',', Qt::SkipEmptyParts);
QList<QStandardItem*> items;
for (int i = 0; i < row.size(); i++)
{
QStandardItem* item = new QStandardItem(row.at(i));
items.append(item);
}
model->appendRow(items);
}
file.close();
return true;
}
// 寫入CSV文件
bool writeCsv(QString filePath, QStandardItemModel* model)
{
QFile file(filePath);
if (!file.open(QIODevice::WriteOnly | QIODevice::Text))
return false;
QTextStream stream(&file);
for (int i = 0; i < model->rowCount(); i++)
{
QStringList row;
for (int j = 0; j < model->columnCount(); j++)
{
QString cell = model->index(i, j).data().toString();
row.append(cell);
}
stream << row.join(",") << "\n";
}
file.close();
return true;
}
該示例代碼使用了QStandardItemModel類來保存每行數(shù)據(jù),并使用QTextStream類讀寫文件。在讀取CSV文件時(shí),使用QStandardItemModel的appendRow()函數(shù)向模型中添加新行,并在每行中保存對應(yīng)的QStandardItem對象的指針。在寫入CSV文件時(shí),從QStandardItemModel中取出每個(gè)單元格的數(shù)據(jù),將其轉(zhuǎn)換成字符串后,保存到QStringList中,并使用QTextStream類的<<運(yùn)算符將數(shù)據(jù)寫入到文件中。
優(yōu)點(diǎn):
- 具有更好的擴(kuò)展性:相對于前兩種實(shí)現(xiàn)方式,使用QStandardItemModel實(shí)現(xiàn)CSV讀寫操作具有更好的擴(kuò)展性和靈活性;
- 數(shù)據(jù)順序可改變:使用QStandardItemModel保存數(shù)據(jù)可以方便地改變數(shù)據(jù)順序,并且可以添加自定義的數(shù)據(jù)項(xiàng)(例如:QComboBox)。
缺點(diǎn):
- 實(shí)現(xiàn)相對復(fù)雜:相對于前兩種實(shí)現(xiàn)方式,使用QStandardItemModel實(shí)現(xiàn)CSV讀寫操作需要考慮到數(shù)據(jù)處理和模型層次結(jié)構(gòu)的復(fù)雜性;
- 內(nèi)存消耗較大:使用QStandardItemModel來保存每行數(shù)據(jù),可能會(huì)導(dǎo)致內(nèi)存消耗較大。
附:QT讀取csv文件并且繪制折線圖
void MainWindow::readcsvfile() //讀取csv
{
QFile csvFile("C:/Users/Administrator/Desktop/Demo/0702.CSV");
QStringList csvList;
csvList.clear();
if (csvFile.open(QIODevice::ReadWrite)) //對csv文件進(jìn)行讀寫操作
{
QTextStream stream(&csvFile);
while (!stream.atEnd())
{
csvList.push_back(stream.readLine()); //保存到List當(dāng)中
}
csvFile.close();
}
else
{
QMessageBox::about(NULL, "csv文件", "未打開該文件!");
}
int i = 0;
Q_FOREACH(QString str, csvList) //遍歷List
{
i = i + 1;
QStringList valsplit = str.split(","); //分隔字符串
if(i > 2)
{
//得到深度、聲速、溫度
QString depth = valsplit[0];
QString sonicvelocity = valsplit[1];
QString temperature = valsplit[2];
double depthvalue = depth.toDouble();
double sonicvalue = sonicvelocity.toDouble();
double tempvalue = temperature.toDouble();
//Q//MessageBox::warning(NULL, "dd", QString::number(tempvalue));
QPointF point;
point.setX(depthvalue);
point.setY(sonicvalue);
QPointF point2;
point2.setX(depthvalue);
point2.setY(tempvalue + 1510);
vectors.append(point);
vector2.append(point2);
}
}
}
void MainWindow::lineChart() //繪制圖
{
//設(shè)置X,Y標(biāo)題
ui->qwtPlot->setAxisTitle(QwtPlot::xBottom, QString::fromLocal8Bit("深度(m)"));
ui->qwtPlot->setAxisTitle(QwtPlot::yLeft, QString::fromLocal8Bit("聲速(m/s)"));
ui->qwtPlot->setAxisTitle(QwtPlot::yRight, QString::fromLocal8Bit("溫度(°C)"));
ui->qwtPlot->enableAxis(QwtPlot::yRight,true);
ui->qwtPlot->setAxisScale(QwtPlot::yLeft,1538,1540,0.2);
ui->qwtPlot->setAxisScale(QwtPlot::xBottom,0,30,2);
ui->qwtPlot->setAxisScale(QwtPlot::yRight,28,30,0.2);
//ui->qwtPlot->set
//構(gòu)造曲線數(shù)據(jù)
QwtPointSeriesData* series = new QwtPointSeriesData(vectors);
//設(shè)置網(wǎng)格
QwtPlotGrid* grid = new QwtPlotGrid();
grid->setPen(QColor(222, 222, 222), 1);
grid->attach(ui->qwtPlot);
//create plot item
QwtPlotCurve* curve1 = new QwtPlotCurve(QString::fromLocal8Bit("聲速"));
//設(shè)置數(shù)據(jù)
curve1->setData(series);
//設(shè)置畫筆顏色==就是圖像顏色
curve1->setPen(QColor(255, 0, 0), 2, Qt::SolidLine);
//使曲線更光滑
curve1->setCurveAttribute(QwtPlotCurve::Fitted, true);
//把曲線附加到qwtPlot上
curve1->attach(ui->qwtPlot);
//添加溫度-深度曲線
//構(gòu)造曲線數(shù)據(jù)
QwtPointSeriesData* series2 = new QwtPointSeriesData(vector2);
//create plot item
QwtPlotCurve* curve2 = new QwtPlotCurve(QString::fromLocal8Bit("溫度"));
//設(shè)置數(shù)據(jù)
curve2->setData(series2);
//設(shè)置畫筆顏色=圖像顏色
curve2->setPen(QColor(127, 222, 335), 2, Qt::SolidLine);
//使曲線更光滑
curve2->setCurveAttribute(QwtPlotCurve::Fitted, true);
//把曲線附加到qwtPlot上
curve2->attach(ui->qwtPlot);
//設(shè)置圖例
QwtLegend *legend = new QwtLegend;
legend->setDefaultItemMode(QwtLegendData::ReadOnly);
ui->qwtPlot->insertLegend(legend,QwtPlot::BottomLegend);//插入圖例
ui->qwtPlot->replot();
ui->qwtPlot->show();
}需要第三方庫QWT
運(yùn)行結(jié)果:

最后
本篇博客介紹了四種使用Qt實(shí)現(xiàn)CSV文件讀寫操作的方法,分別是:
- 使用QStringList及QTextStream實(shí)現(xiàn)CSV文件讀寫;
- 使用QTextCodec及QByteArray實(shí)現(xiàn)CSV文件讀寫;
- 使用QStandardItemModel實(shí)現(xiàn)CSV文件讀寫;
每種實(shí)現(xiàn)方式都有自己的優(yōu)缺點(diǎn),在實(shí)際開發(fā)中可以根據(jù)具體應(yīng)用場景選擇適用的實(shí)現(xiàn)方法。
總的來說,對于小型數(shù)據(jù)量的CSV文件,使用QStringList及QTextStream實(shí)現(xiàn)CSV文件讀寫是一個(gè)比較好的選擇,因?yàn)閷?shí)現(xiàn)相對簡單;對于大型數(shù)據(jù)量的CSV文件,使用QTextCodec及QByteArray可以更快地進(jìn)行文件I/O操作;使用QStandardItemModel可以更好地處理數(shù)據(jù)添加、刪除、排序等操作,但相對復(fù)雜一些。而對于使用頻率較高的CSV讀寫操作,可以考慮使用基于Qt的CSV庫或插件,這樣可以更快地實(shí)現(xiàn)CSV文件讀寫操作。
當(dāng)然,在實(shí)際開發(fā)中還涉及到其他問題,例如文件路徑的處理、文件打開失敗處理等,本文示例中并未全部涉及,可根據(jù)具體應(yīng)用場景進(jìn)行擴(kuò)展。
總結(jié)
到此這篇關(guān)于Qt讀寫CSV文件的三種方式及優(yōu)劣對比的文章就介紹到這了,更多相關(guān)Qt讀寫CSV文件內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
淺析string 與char* char[]之間的轉(zhuǎn)換
與char*不同的是,string不一定以NULL('\0')結(jié)束。string長度可以根據(jù)length()得到,string可以根據(jù)下標(biāo)訪問。所以,不能將string直接賦值給char*2013-10-10
基于epoll的多線程網(wǎng)絡(luò)服務(wù)程序設(shè)計(jì)
這篇文章主要為大家詳細(xì)介紹了基于epoll的多線程網(wǎng)絡(luò)服務(wù)程序設(shè)計(jì),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-08-08
OpenCV實(shí)現(xiàn)彩色照片轉(zhuǎn)換成素描卡通片
這篇文章主要為大家詳細(xì)介紹了OpenCV實(shí)現(xiàn)彩色照片轉(zhuǎn)換成素描卡通片,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-01-01
深入了解C語言中的動(dòng)態(tài)內(nèi)存分配
這篇文章主要為大家詳細(xì)介紹了C語言中的動(dòng)態(tài)內(nèi)存分配,文中的示例代碼講解詳細(xì),對我們學(xué)習(xí)C語言有一定的幫助,需要的可以參考一下2022-06-06

