I make a program that reads a file. I have a combobox that reads lines numbers: 1,6,11,..etc. I want to e.g. read lines 1-5 when line number 1 is choosen in combobox and push button is clicked (or read lines 6-10 when line 6 is choosen, end so on).
For now I have this.
int line_counter=1;
if(file.open (QIODevice::ReadOnly | QIODevice::Text))
{
while(!stream.atEnd())
{
line = stream.readLine ();
if(!line.isNull ())
{
if((line_counter%5)==1)
ui->comboBox->addItem (line);
line_counter++;
}
}
}
stream.flush ();
file.close ();
void Servers::on_pushButton_clicked()
{
if(file.open (QIODevice::ReadOnly | QIODevice::Text))
{
for(int i=line_counter;i<line_counter+5;i++)
{
ui->textBrowser->setText(stream.readLine(i));
}
}
file.close ();
}
You can avoid reading from file each team you want to update textBrowser if the text is already in the comboBox.
First of all connect the pushButton signal with your method:
connect(ui->pushButton, &QPushButton::clicked, this, &Servers::on_pushButton_clicked);
Then change on_pushButton_clicked like so:
void Servers::on_pushButton_clicked()
{
if(file.open (QIODevice::ReadOnly | QIODevice::Text))
{
int index = ui->comboBox->currentIndex();
int from = 5 * index;
int to = from + 5;
QTextStream stream(&file);
int lineCount = 0;
QString text;
QString line;
while (stream.readLineInto(&line)) {
if (from >= lineCount && lineCount < to) {
text += line;
text += '\n';
}
lineCount++;
}
ui->textBrowser->setText(text.toString());
}
}
Related
I'm exporting data to csv. I can export if datas around 8K or 10K but when I try to export data around 100K I get a warning "program not responding".
void MainWindow::exportArraysToCSV(QStringList labelList, QList < QList < double >> dataColums, QChar sep) {
QString filters("CSV files (*.csv);;All files (*.*)");
QString defaultFilter("CSVi files (*.csv)");
QString fileName = QFileDialog::getSaveFileName(0, "Save file", QCoreApplication::applicationDirPath(),
filters, & defaultFilter);
QFile file(fileName);
if (file.open(QFile::WriteOnly | QFile::Append)) {
QTextStream data( & file);
QStringList strList;
QString formula;
foreach(auto label, labelList) {
if (label.length() > 0){
strList.append("," + label + ",");
}
else
strList.append("");
}
data << strList.join(",") << "\n";
int maxRowCount = 0;
foreach(auto column, dataColums)
maxRowCount = qMax(maxRowCount, column.count());
for (int i = 5; i < maxRowCount; ++i) // rows
{
strList.clear();
for (int j = 0; j < 2; ++j) // columns
{
if (i < dataColums[j].count())
strList.append(QString::number(dataColums[j][i], 'f'));
else
strList.append("\"\" ");
}
data << strList.join(",") + "\n";
}
data << "=SUM(A2:A1255)";
file.close();
}
}
I have a text file test1.txt:
aaa|aaa|aaa
bbb|bbb|bbb
ccc|ccc|ccc
ddd|ddd|ddd
File has 4 rows as you can see. I use this code to read the content of the file and get each line as a separated string:
#include "SPIFFS.h"
String file_content = "";
char VALUE [1024] = {'\0'};
void setup() {
Serial.begin(9600);
if (!SPIFFS.begin(true)) {
Serial.println("An Error has occurred while mounting SPIFFS");
return;
}
File file = SPIFFS.open("/test1.txt");
if (!file) {
Serial.println("Failed to open file for reading");
return;
}
uint16_t i = 0;
while (file.available()) {
VALUE[i] = file.read();
Serial.println (VALUE[i]);
i++;
}
VALUE[i] ='\0';
Serial.println("Raw print");
Serial.println (VALUE); //use for debug
Serial.println("String print");
String myString = String(VALUE);
Serial.println (myString);
file.close();
int delimiter, delimiter_1, delimiter_2, delimiter_3, delimiter_4;
delimiter = myString.indexOf("\n");
delimiter_1 = myString.indexOf("\n", delimiter + 1);
delimiter_2 = myString.indexOf("\n", delimiter_1 +1);
delimiter_3 = myString.indexOf("\n", delimiter_2 +1);
delimiter_4 = myString.indexOf("\n", delimiter_3 +1);
// Define variables to be executed on the code later by collecting information from the readString as substrings.
String row1 = myString.substring(delimiter + 1, delimiter_1);
String row2 = myString.substring(delimiter_1 + 1, delimiter_2);
String row3 = myString.substring(delimiter_2 + 1, delimiter_3);
String row4 = myString.substring(delimiter_3 + 1, delimiter_4);
Serial.println("Rows print");
Serial.println(row1);
Serial.println(row2);
Serial.println(row3);
Serial.println(row4);
}
void loop() {}
Output of Rows print is:
Rows print
bbb|bbb|bbb
ccc|ccc|ccc
ddd|ddd|ddd
aaa|aaa|aaa
Why is the "aaa" row thelast one and not first one? Basically delimiter_1 is "bbb" row instead be "aaa" row, and delimiter_4 is "aaa" row instead "ddd" row.
Thanks.
Try this:
#include <SPIFFS.h>
using namespace std;
void setup() {
Serial.begin(115200);
if (!SPIFFS.begin(true)) {
Serial.println("An Error has occurred while mounting SPIFFS");
return;
}
File file = SPIFFS.open("/test1.txt");
if (!file) {
Serial.println("Failed to open file for reading");
return;
}
vector<String> v;
while (file.available()) {
v.push_back(file.readStringUntil('\n'));
}
file.close();
for (String s : v) {
Serial.println(s);
}
}
void loop() {}
Output:
aaa|aaa|aaa
bbb|bbb|bbb
ccc|ccc|ccc
ddd|ddd|ddd
EDIT:
If you want to manipulate individual element, you could use regular for-loop iteration. See example below:
for (int i = 0; i < v.size(); i++){
Serial.println(v[i]);
}
I'm working on a project with Flash data saving. I'm using SPIFFS library for ESP32, I'm currently attempting to store the data from each line into a String. Since I have control of how many content can go into the file, it won't need more than 3 Strings to store the data. I could easily manage to store the first line content using readStringUntil. But I can't manage to get the content from 2 and 3 line.
For the first line I'm using this code:
//Pegar a primeira linha do arquivo, onde serĂ¡ armazenado o nome do WIFI (ssid)
void first_line (){
file = SPIFFS.open("/wifi.txt", "r");
while (file.available()) {
String first_line = file.readStringUntil('\n');
Serial.print(first_line);
break;
}
file.close();
}
I'm writing the code into the File with this function:
// Escrever mensagem dentro do arquivo
void write_file_info(String message) {
file = SPIFFS.open("/wifi.txt", FILE_WRITE);
if (!file){
Serial.println("Error opening file");
return;
}else{
Serial.println("Success opening file");
}
if (file.println(message)){
Serial.println("File was written");
}else{
Serial.println("File was not written");
}
file.close();
}
And I'm using Append to add the second and third line:
void append_file_info (String message){
file = SPIFFS.open("/wifi.txt", FILE_APPEND);
if (!file){
Serial.println("Erro ao realizar APPEND ao arquivo");
}
if (file.println(message)){
Serial.println("File was added");
}else{
Serial.println("File was not added");
}
file.close();
}
This is the current output, file size is just for manage and "content inside file" is just for reference:
File size: 37
Content inside file:
first line
second line
thrid line
This is how I'm reading the file:
void read_file_info() {
file = SPIFFS.open("/wifi.txt");
Serial.print("\nFile size: ");
Serial.println(file.size());
Serial.print("Content inside file: \n");
while (file.available()){
Serial.write(file.read());
}
Serial.println("\n");
file.close();
delay(3000);
}
I thought on trying to read the data after '\n', but couldn't find any documentation on reading after certain string.
I tried creating a buffer and splitting it later, the output from the buffer is correct but I can't split it into strings correctly:
void second_line (){
file = SPIFFS.open("/wifi.txt", "r");
char buffer[64];
while (file.available()) {
int l = file.readBytesUntil('\n', buffer, sizeof(buffer));
buffer[l] = 0;
Serial.println(buffer);
}
file.close();
}
It would be simpler using vector:
#include <SPIFFS.h>
using namespace std;
void setup() {
Serial.begin(115200);
if (!SPIFFS.begin(true)) {
Serial.println("An Error has occurred while mounting SPIFFS");
return;
}
File file = SPIFFS.open("/wifi.txt");
if (!file) {
Serial.println("Failed to open file for reading");
return;
}
vector<String> v;
while (file.available()) {
v.push_back(file.readStringUntil('\n'));
}
file.close();
for (String s : v) {
Serial.println(s);
}
}
void loop() {}
Use v[0] to get first line, v[1] for second line, v[2] for third line and so on.
I could manage to get it working like this:
void all_lines (){
file = SPIFFS.open("/wifi.txt", "r");
int i = 0;
char buffer[64];
String line_one, line_two, line_three;
while (file.available()) {
int l = file.readBytesUntil('\n', buffer, sizeof(buffer));
buffer[l] = 0;
if (i == 0) {
line_one = buffer;
}
if (i == 1) {
line_two = buffer;
}
if (i == 2) {
line_three = buffer;
}
i++;
if (i == 3){
break;
}
}
file.close();
}
I want to read some data from a file with QT and then show data in a QTableWidget through a QComboBox.
void DemoDataView::on_comboBox_activated(const QString &arg1)
{
ui->tableWidget->setColumnCount(5);
ui->tableWidget->setRowCount(21);
ui->tableWidget->verticalHeader()->setVisible(false);
ui->tableWidget->setHorizontalHeaderLabels(QString("Age Range ; Male Population ; Male Percentage ; Female Population ; Female Percentage").split(";"));
ui->tableWidget->resizeColumnsToContents();
ui->tableWidget->resizeRowsToContents();
QFile inputFile("./data.txt");
if(!inputFile.open(QIODevice::ReadOnly))
{
QMessageBox::information(0, "Error", inputFile.errorString());
}
QTextStream in(&inputFile);
int rows = 0;
while(!in.atEnd()) {
QString mLine = in.readLine();
QStringList fields = mLine.split(" ");
QStringList::iterator it = fields.begin();
QString regName = *it;
ui->label->setText(arg1);
if(regName != "<END>" && QString::compare(regName, arg1) == 0) {
ui->label->setText(regName);
it++;
QString ageRange = *it;
it++;
QString nMale = *it;
double male = nMale.toDouble();
it++;
QString nFemale = *it;
double female = nFemale.toDouble();
ui->tableWidget->setItem(rows, 0, new QTableWidgetItem(ageRange));
ui->tableWidget->setItem(rows, 1, new QTableWidgetItem(nMale));
ui->tableWidget->setItem(rows, 3, new QTableWidgetItem(nFemale));
ui->tableWidget->setItem(rows, 2, new QTableWidgetItem(malePercCalc(male, female)));
ui->tableWidget->setItem(rows, 4, new QTableWidgetItem(femalePercCalc(male, female)));
rows++;
}
inputFile.close();
}
}
The file is in both the project folder and the build project folder.
When I run the application everything works good but in the Application Output tab I have this error message:
"QIODevice:: read (QFile, "./data.txt"): device not open"
Every time I click on a QComboBox item.
If it can be useful, this is the filling code of the QComboBox:
void DemoDataView::setComboBoxRegion() {
QFile inputFile("./data.txt");
if(!inputFile.open(QIODevice::ReadOnly))
{
QMessageBox::information(0, "Error", inputFile.errorString());
}
QTextStream in(&inputFile);
while(!in.atEnd()) {
QString mLine = in.readLine();
QStringList fields = mLine.split(" ");
QStringList::iterator it = fields.begin();
QString regName = *it;
if(regName != "<END>") {
if(ui->comboBox->findText(regName) == -1){
ui->comboBox->addItem(regName);
}
}
}
inputFile.close();
}
Your problem is that you are calling:
inputFile.close();
INSIDE of your loop, which means it is closed in the first loop. I can't really think of any cases that this would be the desired thing to happen;
To solve this, you should move it to the outside of the loop.
I wrote the below code for a qt gui to view the query output in a QTableView(Model oriented). now i want to save this output as a .csv or .txt file. There were suggestions to use QTableWidget(Item oriented) but I would like to stick to the model based approach.
void MainWindow::on_pushButton_clicked()
{
db = QSqlDatabase::addDatabase("QOCI");
db.setHostName("host");
db.setDatabaseName("db");
db.setUserName("uid");
db.setPassword("pw");
db.setPort(port);
QString MyQuery = ui->lineEdit->text();
if (db.open())
{
qDebug()<<QDateTime::currentDateTime()<<"QUERY DONE SUCCESSFULLY ";
this->model=new QSqlQueryModel();
model->setQuery(MyQuery);
ui->tableView->setModel(model);
}
else
{
qDebug()<<QDateTime::currentDateTime()<<"YOU FORGOT THE QUERY "<<db.lastError().text();
}
}
any guidelines ???
You may customize it according to your actual needs:
// [Collect model data to QString]
QString textData;
int rows = model->rowCount();
int columns = model->columnCount();
for (int i = 0; i < rows; i++) {
for (int j = 0; j < columns; j++) {
textData += model->data(model->index(i,j)).toString();
textData += ", " // for .csv file format
}
textData += "\n"; // (optional: for new line segmentation)
}
// [Save to file] (header file <QFile> needed)
// .csv
QFile csvFile("test.csv");
if(csvFile.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
QTextStream out(&csvFile);
out << textData;
csvFile.close();
}
// .txt
QFile txtFile("test.txt");
if(txtFile.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
QTextStream out(&txtFile);
out << textData;
txtFile.close();
}
You can save your model to a text file by :
QFile f( "table.txt" );
if( f.open( QIODevice::WriteOnly ) )
{
QTextStream ts( &f );
QStringList strList;
for (int i=0; i<model->rowCount(); i++)
{
strList.clear();
for (int j=0; j<model->columnCount(); j++)
strList << model->data(model->index(i,j)).toString();
ts << strList.join(" ") + "\n";
}
f.close();
}
Here the model data are saved one row in each line separated by space. If you want to separate them by some other character like comma you can just replace the parameter on the join like :
ts << strList.join(",") + "\n";
here is a way to export a qtableview to a csv, including the column names using qt
void staticmethods::exportTableViewToCSV(QTableView *table) {
QString filters("CSV files (*.csv);;All files (*.*)");
QString defaultFilter("CSV files (*.csv)");
QString fileName = QFileDialog::getSaveFileName(0, "Save file", QCoreApplication::applicationDirPath(),
filters, &defaultFilter);
QFile file(fileName);
QAbstractItemModel *model = table->model();
if (file.open(QFile::WriteOnly | QFile::Truncate)) {
QTextStream data(&file);
QStringList strList;
for (int i = 0; i < model->columnCount(); i++) {
if (model->headerData(i, Qt::Horizontal, Qt::DisplayRole).toString().length() > 0)
strList.append("\"" + model->headerData(i, Qt::Horizontal, Qt::DisplayRole).toString() + "\"");
else
strList.append("");
}
data << strList.join(";") << "\n";
for (int i = 0; i < model->rowCount(); i++) {
strList.clear();
for (int j = 0; j < model->columnCount(); j++) {
if (model->data(model->index(i, j)).toString().length() > 0)
strList.append("\"" + model->data(model->index(i, j)).toString() + "\"");
else
strList.append("");
}
data << strList.join(";") + "\n";
}
file.close();
}
}