> 文章列表 > Qt读写CSV文件的几种方式及优劣

Qt读写CSV文件的几种方式及优劣

Qt读写CSV文件的几种方式及优劣

前言

作为一种常见的数据交换格式,CSV(Comma Separated Values)文件常常用于数据导出和导入等场合。在实际开发中,我们也需要使用Qt来实现CSV文件的读写操作。本篇博客将介绍使用Qt实现CSV读写的方法,并分析每种实现方式的优缺点。

一、使用QStringList及QTextStream实现CSV文件读写

本方法使用QStringList来保存每行数据,使用QTextStream类读写文本文件。具体实现代码如下:

// 读取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;
}

该示例代码运用了QTextStream的readLine()和<<运算符来实现CSV文件数据的读写。需要注意的是,在读取CSV文件时,要使用QStringList的split()函数来将每行拆分为多个字符串,并用字符串列表保存。在写入CSV文件时,要使用QStringList的join()函数来将每行数据转为字符串,并用逗号分隔,产生一条CSV行,最后一行不应该有逗号。

优点:

  • 实现简单:使用QStringList和QTextStream实现CSV读写操作非常简单,能够快速上手;
  • 代码量少:相对其他实现方式,该方法实现的代码量较少。

缺点:

  • 写入数据顺序不能改变:当数据量大的时候,使用该方法逐行写入文件,文件I/O开销相对较大,导致写入速度变慢。同时,该实现方式要求数据顺序不能改变,因为每行数据只存储在单独的QStringList中。

二、使用QTextCodec及QByteArray实现CSV文件读写

本方法使用QTextCodec来处理编码问题,并使用QByteArray来读写文件。具体实现如下:

// 读取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文件时使用了QTextCodec的codecForName()方法来指定文件编码为UTF-8,使用QByteArray类保存文件数据,通过QTextCodec::toUnicode()函数将字节数组转换成QString对象。在写入CSV文件时,使用QByteArray类保存每行数据,并将数据编码成字节数组后写入文件。

优点:

  • 适用性广泛:该实现方式适用性广泛,可以处理各种不同的字符编码;
  • 写入速度快:使用QByteArray类来读写文件,文件I/O开销相对较少。

缺点:

  • 实现复杂:相对于第一种实现方式,该方法需要处理编码问题和字节流转换问题,因此实现方式相对复杂一些。

三、使用QStandardItemModel实现CSV文件读写

本方法使用QStandardItemModel来保存每行数据,并使用QTextStream来读写文件。具体实现如下:

// 读取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类来保存每行数据,并使用QTextStream类读写文件。在读取CSV文件时,使用QStandardItemModel的appendRow()函数向模型中添加新行,并在每行中保存对应的QStandardItem对象的指针。在写入CSV文件时,从QStandardItemModel中取出每个单元格的数据,将其转换成字符串后,保存到QStringList中,并使用QTextStream类的<<运算符将数据写入到文件中。

优点:

  • 具有更好的扩展性:相对于前两种实现方式,使用QStandardItemModel实现CSV读写操作具有更好的扩展性和灵活性;
  • 数据顺序可改变:使用QStandardItemModel保存数据可以方便地改变数据顺序,并且可以添加自定义的数据项(例如:QComboBox)。

缺点:

  • 实现相对复杂:相对于前两种实现方式,使用QStandardItemModel实现CSV读写操作需要考虑到数据处理和模型层次结构的复杂性;
  • 内存消耗较大:使用QStandardItemModel来保存每行数据,可能会导致内存消耗较大。

最后

本篇博客介绍了四种使用Qt实现CSV文件读写操作的方法,分别是:

  • 使用QStringList及QTextStream实现CSV文件读写;
  • 使用QTextCodec及QByteArray实现CSV文件读写;
  • 使用QStandardItemModel实现CSV文件读写;

每种实现方式都有自己的优缺点,在实际开发中可以根据具体应用场景选择适用的实现方法。

总的来说,对于小型数据量的CSV文件,使用QStringList及QTextStream实现CSV文件读写是一个比较好的选择,因为实现相对简单;对于大型数据量的CSV文件,使用QTextCodec及QByteArray可以更快地进行文件I/O操作;使用QStandardItemModel可以更好地处理数据添加、删除、排序等操作,但相对复杂一些。而对于使用频率较高的CSV读写操作,可以考虑使用基于Qt的CSV库或插件,这样可以更快地实现CSV文件读写操作。

当然,在实际开发中还涉及到其他问题,例如文件路径的处理、文件打开失败处理等,本文示例中并未全部涉及,可根据具体应用场景进行扩展。