1

I am trying to read data from a QTableWidget, and save them in a CSV file.

The values saved in the file are correct, but for the first column in every row there is an unwanted character in the beginning.

Here is my code:

void Task::on_button_Export_clicked()
{
    QString fileName = QFileDialog::getSaveFileName(this,tr("Export Task List"), "",tr("CSV Files (*.csv)"));
    if (fileName.isEmpty())
            return;
    else
    {
        QFile file(fileName);
        if (!file.open(QIODevice::WriteOnly))
        {
            QMessageBox::information(this, tr("Unable to open file"),
            file.errorString());
            return;
        }
        QDataStream out(&file);
        out.setVersion(QDataStream::Qt_5_4);
        int rowCount = ui->tableWidget->rowCount();
        int colCount = ui->tableWidget->columnCount();
        for (int i = 0; i < rowCount; i++)
         {
            QString str(QString::null);

           /* if (i > 0)
            {
               str = "\n";
            }*/

            for (int j = 0; j < colCount; j++)
            {
               if (j > 0)
               {
                  str += ",";
               }
               QTableWidgetItem* item = ui->tableWidget->item(i,j);
               str += item->data(Qt::DisplayRole).toString();
            }
            str += "\n";
            out << str;
         }
    }
}

The saved file looks like this:

ÎDPC Task
ÞMain Task
ÌWorkLoop
ÐWorkLoop
ÌIST0
ÊIST1
ÆIST2

I am using Qt 5.4.0.

Any help here would be greatly appreciated.

rocambille
  • 15,398
  • 12
  • 50
  • 68
Vishal Khemani
  • 171
  • 2
  • 13
  • `QString str(QString::null);` - what is this? Just write `QString str;`. By the way, there are `QTextStream` class for building strings. – Dmitry Sazonov Oct 20 '16 at 10:16
  • I tried String str first. My guess was that it was getting some garbag value so later changed it to QString str(QString::null) to initialize it with null – Vishal Khemani Oct 20 '16 at 10:32

2 Answers2

1

Your else in the beginning is useless if you use return to ends execution of the function (you didn't use else in the second test).

If you need to write text, you should use a QTextStream instead of a QDataStream which is designed to read/write binary data.

Why using a temporary QString in you loops? You have a stream, use it:

void Task::on_button_Export_clicked() {
    QString fileName = QFileDialog::getSaveFileName(
        this,tr("Export Task List"), "",tr("CSV Files (*.csv)")
    );
    if (fileName.isEmpty()) {
        return;
    }

    QFile file(fileName);
    if (!file.open(QIODevice::WriteOnly)) {
        QMessageBox::information(this, tr("Unable to open file"),
        file.errorString());
        return;
    }

    QTextStream out(&file);
    int rowCount = ui->tableWidget->rowCount();
    int colCount = ui->tableWidget->columnCount();

    for (int i = 0; i < rowCount; i++) {
        /* if (i > 0) {
            out << "\n";
        }*/
        for (int j = 0; j < colCount; j++) {
            if (j > 0) {
                out << ",";
            }
            QTableWidgetItem* item = ui->tableWidget->item(i,j);
            out << item->data(Qt::DisplayRole).toString();
        }
        out << "\n";
    }
}
rocambille
  • 15,398
  • 12
  • 50
  • 68
1

Don't use QDataStream for saving text files. Use QTextStream. QDataStream use it's own serialization format instead of writing plain text.

For strings, first two bytes is length, then it's content (2 bytes per char). Your "garbage" is a length of each string. You see only one char, because your file is in unicode.

Dmitry Sazonov
  • 8,801
  • 1
  • 35
  • 61