qtcsv
Author: Antony Cherepanov
E-mail: [email protected]
Small easy-to-use library for reading and writing csv-files in Qt.
Tested on Ubuntu 14.04 with gcc 4.8.4, Qt 4.8 and higher.
Table of contents
Quick Example
#include <QList>
#include <QStringList>
#include <QDir>
#include <QDebug>
#include "stringdata.h"
#include "reader.h"
#include "writer.h"
int main()
{
// prepare data that you want to save to csv-file
QStringList strList;
strList << "one" << "two" << "three";
QtCSV::StringData strData;
strData.addRowValues(strList);
strData.addEmptyRow();
strData << strList << "this is the last row";
// write to file
QString filePath = QDir::currentPath() + "/test.csv";
QtCSV::Writer::write(filePath, strData);
// read data from file
QList<QStringList> readData = QtCSV::Reader::readToList(filePath);
for ( int i = 0; i < readData.size(); ++i )
{
qDebug() << readData.at(i).join(",");
}
return 0;
}
Usage
There are three main classes: Reader, Writer and AbstractData.
AbstractData
AbstractData is a pure abstract class that provide interface for a container class. Here is how it looks:
class AbstractData
{
public:
explicit AbstractData() {}
virtual ~AbstractData() {}
virtual void addEmptyRow() = 0;
virtual void addRow(const QStringList& values) = 0;
virtual void clear() = 0;
virtual bool isEmpty() const = 0;
virtual int rowCount() const = 0;
virtual QStringList rowValues(const int& 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.
If you have said Pure Abstract Class, you must also say Implementation. Don't worry, we have some:
StringData
StringData have the same interface as AbstractData (plus some useful functions for inserting rows, removing rows and so on) and stores all data as strings. It's useful when information that you want to save in csv-file is represented as strings.
VariantData
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.
Reader
Use Reader class to read csv-files. It's very simple. It has only two functions:
- Read data to QList<QStringList>
QList<QStringList> readToList(const QString& filePath,
const QString& separator,
const QString& textDelimeter,
QTextCodec* codec);
- filePath - string with absolute path to existent csv-file (example: "/home/user/my-file.csv");
- separator (optional) - delimeter symbol, that separate elements in a row (by default it is comma - ",");
- textDelimeter (optional) - text delimeter symbol that enclose each element in a row (by default it is double quoute - ");
- codec (optional) - pointer to the codec object that will be used to read data from the file (by default it is UTF-8 codec).
As a result function will return QList<QStringList> that holds content of the file. If all went smooth, list will not be empty and size of it will be equal to the number of rows in csv-file. Each QStringList will contain elements of the corresponding row.
- Read data to AbstractData-based container
bool readToData(const QString& filePath,
AbstractData& data,
const QString& separator,
const QString& textDelimeter,
QTextCodec* codec);
Second function is a little more advanced and, I hope, a little more useful.
- filePath - string with absolute path to existent csv-file;
- data - reference to AbstractData-based class object;
- separator (optional) - delimeter symbol;
- textDelimeter (optional) - text delimeter symbol;
- codec (optional) - pointer to the codec object.
Function will save content of the file in data object, using virtual function AbstractData::addRow(QStringList). If you pass to the function Reader::readToData() object of class StringData or VariantData, elements of csv-file will be saved in them as strings.
If you are not happy with this fact, you can create your own AbstractData-based container class and implement function addRow(QStringList) in a way you want it.
For example, if you know, that each row of your csv-file contains 3 elements (integer value, floating-point value and string), then in function addRow(QStringList) you can convert first element of QStringList to int, second - to double and save all three elements to some internal container (or do with them whatever you want).
Writer
Use Writer class to write to csv-files. It has only one function:
bool Writer::write(const QString& filePath,
const AbstractData& data,
const QString& separator,
const QString& textDelimeter,
const WriteMode& mode,
const QStringList& header,
const QStringList& footer,
QTextCodec* codec)
- filePath - string with absolute path to csv-file (new or existent);
- data - object, that contains information that you want to write to csv-file.
Writer internally will use QStringList AbstractData::rowValues(int) function to get row values; - separator (optional) - delimeter symbol (by default it is comma - ",");
- textDelimeter (optional) - text delimeter symbol that enclose each element in a row (by default it is double quoute - ");
- mode (optional) - write mode flag.
If it set to WriteMode::REWRITE and csv-file exist, then csv-file will be rewritten. If mode set to WriteMode::APPEND and csv-file exist, then new information will be appended to the end of the file.
By default mode set to WriteMode::REWRITE. - header (optional) - strings that will be written at the beginning of the file, separated with defined separator (empty by default);
- footer (optional) - strings that will be written at the end of the file, separated with defined separator (empty by default);
- codec (optional) - pointer to the codec object that will be used to write data to the file (by default it is UTF-8 codec).
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 delimeter symbols (or double quoute if you have set empty string as text delimeter symbol).
Requirements
Qt 4.8 and higher.
It is quite possible, that library will be successfully built with older Qt
versions (4.7, 4.6, ...).
Build
cd /path/to/folder/with/qtcsv
qmake -r
make
Run tests
If you want to run tests, then use this commands:
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$PWD/src
make check
Installation
On Unix-like OS you can install qtcsv library using this command:
sudo make install
sudo ldconfig -n -v /usr/local/lib
This command will copy all compiled files (libqtcsv.so*) from "./src" folder to "/usr/local/lib". Also all headers files will be copied from "./src/include" folder to "/usr/local/include/qtcsv".
All installation settings are defined in ./src/src.pro file. See libheaders and target variables.
For additional information, see Qt documentation about files installation.
Examples
If you want to try qtcsv, you can download qtcsv-example project. Don't forget to read README file!
Other
If you want to know more about csv-file format, read RFC 4180 standard.
Also on this page you can find useful tips about how should look proper csv-file.