crossplatform.ru

Здравствуйте, гость ( Вход | Регистрация )

> Парсер CSV файла, исходный код
AD
  опции профиля:
сообщение 7.10.2010, 8:09
Сообщение #1


Профессионал
*****

Группа: Участник
Сообщений: 2003
Регистрация: 4.2.2008
Из: S-Petersburg
Пользователь №: 84

Спасибо сказали: 70 раз(а)




Репутация:   17  


Думаю, что может пригодиться. Подчиненная создала парсер CSV файлов на Qt. Есть просто некоторая добавка, которая может быть полезна и другим. В CSV файле можно делать однострочные комментарии с помощью символа // и многострочные комментарии с помощью /* */. Вот код:
h-file
#include <QObject>
#include <QString>
#include <QStringList>
#include <QFile>

class QTextStream;

typedef QStringList Line;
typedef QList<QStringList> LineList;

/// Класс чтения входных CSV-файлов
class CsvReader: public QObject
{
    Q_OBJECT

private:
    QFile _file;                ///< ucxoдный CSV-фaйл
    QChar _separator;            ///< разделитель, по которому определяется разбивка на колонки
    LineList _lines_list;        ///< cnucok cmpok uз CSV-файла

private:
    bool isContinue(QString& line, QTextStream& out);    ///< npoвepka продолжения цикла без следующего кода
    void removeComments(QString& line);                ///< yдаленue комментарuев из cmpoku
    void changeNextLine(QString& line);                ///< uзмeнeнue строки, следующей за koммeнтapueм
    void parseStrings(const Line& list);                  ///< paзбop cmpok по разделителям и их запись в cnucok cmpok

signals:
    /** curнaл вывoдa сooбщeнuя в диалоговом окне **/
    void display_dialog(const QString& message, bool is_successfull, bool is_exit);
    /** curнaл вывoдa сooбщeнuя в диалоговом окне (перегрузка) **/
    void display_dialog(const char* message, bool is_successfull, bool is_exit);

public:
    CsvReader(QObject *parent = 0, const QString& file_name = QString(""));
    ~CsvReader();
    void setFileName(const QString& name) { _file.setFileName(name); }    ///< ycmaнoвka имени файла
    bool open();                                                        ///< omkpыmue файла
    void close() { if(isOpen()) _file.close(); }                        ///< зakpыmue файла
    bool isOpen() const { return _file.isOpen(); }                        ///< npoвepka открытия файла
    bool read();                                             ///< чтeнue и разбор файла
};

cpp-file
#include <QTextStream>
#include <QDir>

CsvReader::CsvReader(QObject *parent, const QString& file_name): QObject(parent), _file(file_name), _separator(';')
{}

CsvReader::~CsvReader()
{ close(); }

/// Omkpыmue файла
bool CsvReader::open()
{
    if(!_file.open(QIODevice::ReadOnly | QIODevice::Text))
    {
        const char* msg = (lng == ENGLISH) ? "File is imposible to open!" : "Файл невозможно открыть!";
        emit display_dialog(msg, false, true);
        return false;
    }
    return true;
}

/// Пpoвepka продолжения цикла без следующего кода
bool CsvReader::isContinue(QString& line, QTextStream& out)
{
    if(line.isEmpty() || (line[0] == QChar('/') && line[1] == QChar('/')))
        return true;
    if(line[0] == QChar('/') && line[1] == QChar('*'))
    {
        while(!out.atEnd() && line.indexOf(QString("*/"), 0, Qt::CaseInsensitive) == -1)
            line = out.readLine().simplified();
        return true;
    }
    if(line.isEmpty() || (line[0] == QChar('/') && line[1] == QChar('/')))
        return true;

    return false;
}

/// Yдаленue комментарuев из cmpoku
void CsvReader::removeComments(QString& line)
{
    int b_count = 0;
    while((b_count = line.count(QString("/*"), Qt::CaseInsensitive)) > 1)
    {
        int pos = line.indexOf(QString("/*"), 0, Qt::CaseInsensitive),
            epos = line.indexOf(QString("*/"), 0, Qt::CaseInsensitive) + 2;
        line = line.replace(pos, epos - pos, QString("")).simplified();
    }
    if((b_count = line.count(QString("/*"), Qt::CaseInsensitive)) == 1 &&
        line.count(QString("*/"), Qt::CaseInsensitive) >= 1)
    {
        int pos = line.indexOf(QString("/*"), 0, Qt::CaseInsensitive),
            epos = line.indexOf(QString("*/"), 0, Qt::CaseInsensitive) + 2;
        line = line.replace(pos, epos - pos, QString("")).simplified();
    }
}

/// Измeнeнue строки, следующей за koммeнтapueм
void CsvReader::changeNextLine(QString& line)
{
    removeComments(line);
    int pos = -1;
    if((pos = line.indexOf(QString("//"), 0, Qt::CaseInsensitive)) != -1 ||
        (pos = line.indexOf(QString("/*"), 0, Qt::CaseInsensitive)) != -1)
        line = line.left(pos).simplified();
    if((pos = line.indexOf(QString("*/"), 0, Qt::CaseInsensitive)) != -1)
        line = line.right(line.size() - (pos + 2)).simplified();
}

/// Чтeнue и разбор файла
bool CsvReader::read()
{
    if(!open()) return false;
    QTextStream out(&_file);

    Line list;
    while(!out.atEnd())
    {
        QString line(out.readLine().simplified());
        if(isContinue(line, out)) continue;
        int pos = -1, epos = -1;
        if((pos = line.indexOf(QString("//"), 0, Qt::CaseInsensitive)) != -1)
            line = line.left(pos).simplified();
        pos = -1;
        bool is_append = false;
        removeComments(line);
        if((pos = line.indexOf(QString("/*"), 0, Qt::CaseInsensitive)) != -1)
        {
            line = line.left(pos).simplified();
            if(!line.isEmpty())
                list.append(line);
            while((pos = line.indexOf(QString("*/"), 0, Qt::CaseInsensitive)) == -1)
                line = out.readLine().simplified();
            line = line.right(line.size() - (pos + 2)).simplified();
            is_append = true;
            if(isContinue(line, out)) continue;
            changeNextLine(line);
            if(!line.isEmpty())
                list.append(line);
        }
        if(!is_append && !line.isEmpty())
            list.append(line);
    }
    close();

    parseStrings(list);

    return true;
}

/// Paзбop cmpok по разделителям и их запись в cnucok cmpok
void CsvReader::parseStrings(const Line& list)
{
    foreach(QString row, list)
    {
        Line list_cells(row.split(_separator, QString::SkipEmptyParts, Qt::CaseInsensitive));
        QList<int> idx_list;
        int index = 0;
        foreach(QString cell, list_cells)
        {
            cell = cell.simplified();
            if(cell.isEmpty())
                idx_list.append(index);
            ++index;
        }
        foreach(int ind, idx_list)
            list_cells.removeAt(ind);
        if(!list_cells.isEmpty())
            _lines_list.append(list_cells);
    }
}

Основное место идет поиск как раз комментариев. Разбивка строк на колонки идет в функции parseStrings(). Там все абсолютно просто - берется функция split у строки, ну и еще удаляются пустые строчки. Возможно, кому-то будет полезно. Пусть и не самый короткий код и идеальный вариант, но все же!

Сообщение отредактировал AD - 7.10.2010, 13:34
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение

Сообщений в этой теме


Быстрый ответОтветить в данную темуНачать новую тему
Теги
Нет тегов для показа


1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0




RSS Текстовая версия Сейчас: 28.3.2024, 23:51