Library for reading and writing csv-files in Qt.
Small easy-to-use library for reading and writing csv-files in Qt.
Qt suppport:
master
(you’re here)qt4_qt5
Tested on:
#include <QList>
#include <QString>
#include <QDir>
#include <QDebug>
#include "qtcsv/stringdata.h"
#include "qtcsv/reader.h"
#include "qtcsv/writer.h"
int main()
{
// prepare data that you want to save to csv-file
QList<QString> strList;
strList << "one" << "two" << "three";
QtCSV::StringData strData;
strData.addRow(strList);
strData.addEmptyRow();
strData << strList << "this is the last row";
// write to file
const auto filePath = QDir::currentPath() + "/test.csv";
QtCSV::Writer::write(filePath, strData);
// read data from file
const auto readData = QtCSV::Reader::readToList(filePath);
for (auto i = 0; i < readData.size(); ++i)
{
qDebug() << readData.at(i).join(",");
}
return 0;
}
Library could be separated into three parts: Reader,
Writer and Containers.
qtcsv library can work with standard Qt containers (like QList) and special data containers.
AbstractData is a pure abstract class that provides
interface for a class of special data containers.
class AbstractData {
public:
virtual ~AbstractData() = default;
virtual void addEmptyRow() = 0;
virtual void addRow(const QList<QString>& values) = 0;
virtual void clear() = 0;
virtual bool isEmpty() const = 0;
virtual qsizetype rowCount() const = 0;
virtual QList<QString> rowValues(qsizetype row) const = 0;
};
As you can see, AbstractData declare virtual functions for adding new rows,
getting rows values, clearing all information and so on. Basic stuff for a
container class.
StringData inhertis interface of AbstractData
class and provides some useful functions for inserting/removing rows and
so on. Class uses strings to store data.
If you store information in different types - integers, floating point
values, strings or (almost) anything else (example: [1, 3.14, “check”]) -
and you don’t want to manually transform each element to string, then you
can use QVariant magic. Wrap your data into QVariants and pass it to
VariantData class. It also inherits interface of AbstractData
plus has several useful methods.
Use Reader class to read csv-files / csv-data. Let’s see it’s functions.
QList<QList<QString>> readToList(
const QString& filePath,
const QString& separator = QString(","),
const QString& textDelimiter = QString("\""),
QStringConverter::Encoding codec = QStringConverter::Utf8);
QList<QList<QString>> readToList(
QIODevice& ioDevice,
const QString& separator = QString(","),
const QString& textDelimiter = QString("\""),
QStringConverter::Encoding codec = QStringConverter::Utf8);
As a result function will return QList<QList<QString>> that holds content
of the file / IO Device. Size of it will be equal to the number of rows
in csv-data source. Each QList<QString> will contain elements of the
corresponding row. On error these functions will return empty list.
bool readToData(
const QString& filePath,
AbstractData& data,
const QString& separator = QString(","),
const QString& textDelimiter = QString("\""),
QStringConverter::Encoding codec = QStringConverter::Utf8);
bool readToData(
QIODevice& ioDevice,
AbstractData& data,
const QString& separator = QString(","),
const QString& textDelimiter = QString("\""),
QStringConverter::Encoding codec = QStringConverter::Utf8);
These functions are little more advanced and, I hope, a little more useful.
Functions will save content of the file / IO Device in data object using virtual
function AbstractData::addRow(QList<QString>). Elements of csv-data will be
saved as strings in objects of StringData / VariantData.
If you would like to convert row elements to the target types on-the-fly during
file reading, please implement your own AbstractData-based container class.
bool readToProcessor(
const QString& filePath,
AbstractProcessor& processor,
const QString& separator = QString(","),
const QString& textDelimiter = QString("\""),
QStringConverter::Encoding codec = QStringConverter::Utf8);
bool readToProcessor(
QIODevice& ioDevice,
AbstractProcessor& processor,
const QString& separator = QString(","),
const QString& textDelimiter = QString("\""),
QStringConverter::Encoding codec = QStringConverter::Utf8);
This function will read csv-data from file / IO Device line-by-line and
pass data to processor object.
AbstractProcessor is an abstract class with two methods:
class AbstractProcessor
{
public:
virtual ~AbstractProcessor() = default;
virtual void preProcessRawLine(QString& /*editable_line*/) {}
virtual bool processRowElements(const QList<QString>& elements) = 0;
};
When Reader opens a csv-data source (file or IO Device), it starts
reading it line by line in a cycle. First of all, Reader passes each
new line to processor’s method preProcessRawLine(QString&). In this method
you can edit the line - replace values, remove sensitive information and so on.
After that Reader parses elements of the row and passes them to processor’s
method processRowElements(QList<QString>). At that step you can do whatever
you want with row elements - convert/edit/save/filter the elements. Please check out
ReadToListProcessor class (defined in reader.cpp) as an example of
such processor.
Use Writer class to write csv-data to files / IO Devices.
bool write(
const QString& filePath,
const AbstractData& data,
const QString& separator = QString(","),
const QString& textDelimiter = QString("\""),
WriteMode mode = WriteMode::REWRITE,
const QList<QString>& header = {},
const QList<QString>& footer = {},
QStringConverter::Encoding codec = QStringConverter::Utf8);
bool write(
QIODevice& ioDevice,
const AbstractData& data,
const QString& separator = QString(","),
const QString& textDelimiter = QString("\""),
const QList<QString>& header = {},
const QList<QString>& footer = {},
QStringConverter::Encoding codec = QStringConverter::Utf8);
Writer uses CRLF as line ending symbols in accordance with standard.
If element of the row contains separator symbol or line ending symbols, such
element will be enclosed by text delimiter symbols (or double quoute if you have set
empty string as text delimiter symbol).
Qt6, only core/base modules.
cd /path/to/folder/with/qtcsv
# Create build directory
mkdir ./build
cd ./build
# Build library. You can choose build type: release or debug
qmake ../qtcsv.pro CONFIG+=[release|debug]
make
# Create build directory for tests
mkdir ./tests
cd ./tests
# Build tests. Besides of setting build type, we set path where linker could find compiled library file.
qmake ../../tests/tests.pro CONFIG+=[release|debug] LIBS+=-L../
make
cd /path/to/folder/with/qtcsv
# Create build directory
mkdir ./build
cd ./build
# Build library and tests. See CMakeLists.txt for list of additional options that you can set.
cmake -DCMAKE_BUILD_TYPE=Release -DBUILD_TESTS=ON ..
make
If you going to build qtcsv library on Windows with MinGW, first of all check that your PATH variable contains paths to Qt and MinGW toolsets.
cd C:\path\to\folder\with\qtcsv
# Create build directory
mkdir .\build
cd .\build
# Build library. You can choose build type: release or debug. Set DESTDIR to current directory.
qmake ..\qtcsv.pro CONFIG+=[release|debug] DESTDIR=%cd%
mingw32-make
# Create build directory for tests
mkdir .\tests
cd .\tests
# Copy library file into 'tests' directory
copy ..\qtcsv.dll .\
# Build tests
qmake ..\..\tests\tests.pro CONFIG+=[release|debug] DESTDIR=%cd%
mingw32-make
cd C:\path\to\folder\with\qtcsv
# Create build directory
mkdir .\build
cd .\build
# Build library and tests. See CMakeLists.txt for list of additional options that you can set.
cmake -G "MinGW Makefiles" -DCMAKE_BUILD_TYPE=Release -DBUILD_TESTS=ON ..
mingw32-make
To run tests use these commands after build of qtcsv:
cd /path/to/folder/with/qtcsv/build/tests
# Set LD_LIBRARY_PATH variable so test binary will know where to search library file.
# Suppose, that library file is located in "build" directory, up a level from current directory.
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$PWD/../
chmod 777 qtcsv_tests
./qtcsv_tests
cd /path/to/folder/with/qtcsv/build/tests
# Copy library file into "tests" directory
copy ..\*qtcsv.dll .\
qtcsv_tests.exe
On Unix-like OS you can install qtcsv library using these commands:
sudo make install
sudo ldconfig -n -v /usr/local/lib
These commands will copy all compiled files (libqtcsv.so*) from build
folder to “/usr/local/lib”. Also all headers files will be copied
from “./include” folder to “/usr/local/include/”.
All installation settings are defined in qtcsv.pro file.
See copy_lib_headers and target variables.
For additional information, see Qt documentation about
files installation.
If you would like to try qtcsv, you can download qtcsv-example project.
Don’t forget to read README.md file!
If you want to know more about csv-file format, please read RFC 4180 standard.
Also on this page you can find useful tips about how should look
proper csv-file.
Author: Antony Cherepanov ([email protected])
Contributors: Patrizio “pbek” Bekerle, Furkan “Furkanzmc” Üzümcü, Martin “schulmar” Schulze, cguentherTUChemnitz, David Jung, Nicu Tofan, Florian Apolloner, Michael Pollind, Kuba Ober, Akram Abdeslem Chaima, Bogdan Cristea, Markus Krause