QT File writing with arrays - c++

Im trying to read from csv file into another file. There aren't any errors, I just don't understand why it is not writing into the file. Any help is appreciated. Im very new to QT.
QString arr[581][6];
while (!file.atEnd()) {
QByteArray line = file.readLine();
for (int i=0; i<581; i++){
for(int j=0; j<6; j++){
arr[i][j]=line;
}
}
}
QString Hfilename="c:\Data.txt";
QFile fileH( Hfilename );
if ( fileH.open(QIODevice::ReadWrite) )
{
QTextStream stream( &fileH );
for (int i=0; i<581; i++){
for(int j=0; j<6; j++){
stream<<arr[i][j]<<endl;
}
}
}

Based on the code you provided, please find a working example for the write step (you specified that the read step is alrady working):
#include <QCoreApplication>
#include <QFile>
#include <QTextStream>
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
QString arr[3];
arr[0] = "xxxxxx";
arr[1] = "yyyy";
arr[2] = "zzzz";
QString Hfilename="/home/jhondoe/toto.txt";
QFile fileH( Hfilename );
if ( fileH.open(QIODevice::ReadWrite) )
{
QTextStream stream( &fileH );
for (int i=0; i<3; i++){
stream << arr[i] << endl;
}
}
return a.exec();
}
What changed:
I (my user account) has sufficient rights to write into the output file
If you work on Windows, as #igor-tandetnik said, you have to use double backslashes as separator. You can also use QDir::separator() as native separator for your file path.

Related

how to make 10 copies of initial file, if first file is as-1.txt second should be as-2.txt and so on

Loop isn't making 10 copies and i have no idea how to change file names
#include "iostream"
#include "fstream"
#include "windows.h"
using namespace std;
void main()
{
char str[200];
ifstream myfile("as-1.txt");
if (!myfile)
{
cerr << "file not opening";
exit(1);
}
for (int i = 0; i < 10; i++)
{
ofstream myfile2("as-2.txt");
while (!myfile.eof())
{
myfile.getline(str, 200);
myfile2 << str << endl;
}
}
system("pause");
}
Solution using plain C API from <cstdio>. Easily customizable.
const char* file_name_format = "as-%d.txt"; //Change that if you need different name pattern
const char* original_file_name = "as-1.txt"; //Original file
const size_t max_file_name = 255;
FILE* original_file = fopen(original_file_name, "r+");
if(!original_file)
//file not found, handle error
fseek(original_file, 0, SEEK_END); //(*)
long file_size = ftell(original_file);
fseek(original_file, 0, SEEK_SET);
char* original_content = (char*)malloc(file_size);
fread(original_content, file_size, 1, original_file);
fclose(original_file);
size_t copies_num = 10;
size_t first_copy_number = 2;
char file_name[max_file_name];
for(size_t n = first_copy_number; n < first_copy_number + copies_num; ++n)
{
snprintf(file_name, max_file_name, file_name_format, n);
FILE* file = fopen(file_name, "w");
fwrite(original_content, file_size, 1, file);
fclose(file);
}
free(original_content);
(*) As noted on this page, SEEK_END may not necessarily be supported (i.e. it is not a portable solution). However most POSIX-compliant systems (including the most popular Linux distros), Windows family and OSX support this without any problems.
Oh, and one more thing. This line
while (!myfile.eof())
is not quite correct. Read this question - it explains why you shouldn't write such code.
int main()
{
const int copies_of_file = 10;
for (int i = 1; i <= copies_of_file; ++i)
{
std::ostringstream name;
name << "filename as-" << i << ".txt";
std::ofstream ofile(name.str().c_str());
ofile.close();
}
return 0;
}
That will make 10 copies of a blank .txt file named "filename as-1.txt" "filename as-2.txt" etc.
Note also the use of int main: main always has a return of int, never void

QTableView output save as .csv or .txt

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();
}
}

How do I log several variables with log4cpp at once?

How do I log more than a single string with log4cpp?
E.g. if I want to log all argv's to main:
#include <iostream>
#include <log4cpp/Category.hh>
#include <log4cpp/FileAppender.hh>
#include <log4cpp/PatternLayout.hh>
using namespace std;
int main(int argc, char* argv[]) {
log4cpp::Appender *appender = new log4cpp::FileAppender("FileAppender","mylog");
log4cpp::PatternLayout *layout = new log4cpp::PatternLayout();
layout->setConversionPattern("%d: %p - %m %n");
log4cpp::Category& category = log4cpp::Category::getInstance("Category");
appender->setLayout(layout);
category.setAppender(appender);
category.setPriority(log4cpp::Priority::INFO);
category.info("program started"); // this works fine, I see it in the logfile
for(int i=0; i<argc; ++i) {
// next line does not compile:
category.info("argv["<<i<<"] = '"<<argv[i]<<"'");
}
return 0;
}
the line
category.info("argv["<<i<<"] = '"<<argv[i]<<"'");
does not compile. Obviously the logger does not work as a ostream. What is the log4cpp way to log something like this, preferable at once?
You have two options:
Use printf-style formatting:
for (int i = 0; i < argc; ++i)
{
category.info("argv[%d] = '%s'", i, argv[i]);
}
Use infoStream():
for (int i = 0; i < argc; ++i)
{
category.infoStream() << "argv[" << i << "] = '" << argv[i] << "'";
}
I'd go with the latter.

QBitArray to QByteArray

When we create a text file with this text "ali ata bak", and we use this file as input for the program. The code is running normally. But when we enter "1111111111111111111111" this text in the textfile, Code isnt running expected. So What is the problem?
#include <QtCore/QCoreApplication>
#include <QBitArray>
#include <QByteRef>
#include <QFile>
#include <iostream>
#include <stdlib.h>
#include <QTextStream>
// Buffer Size #num of KB's
#define BUFFER_SIZE_KB 1
// Do not change !!
#define BUFFER_SIZE_BYTE BUFFER_SIZE_KB*1024
#define BUFFER_SIZE_BIT BUFFER_SIZE_BYTE*8
using namespace std;
QBitArray bytesToBits(QByteArray bytes) {
QBitArray bits(bytes.count()*8);
// Convert from QByteArray to QBitArray
for(int i=0; i<bytes.count(); ++i)
for(int b=0; b<8; ++b)
bits.setBit(i*8+b, bytes.at(i)&(1<<b));
return bits;
}
QByteArray bitsToBytes(QBitArray bits) {
QByteArray bytes;
bytes.resize(bits.count()/8);
// Convert from QBitArray to QByteArray
for(int b=0; b<bits.count(); ++b)
bytes[b/8] = ( bytes.at(b/8) | ((bits[b]?1:0)<<(b%8)));
return bytes;
}
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
QString inFilename;
QString outFilename;
QTextStream qtin(stdin);
cout << "Filename : ";
qtin >> inFilename;
outFilename.append("_");
outFilename.append(inFilename);
QFile infile(inFilename);
if (!infile.open(QIODevice::ReadOnly)) {
cout << "\nFile cant opened\n";
system("pause");
return 1;
}
QFile outfile(outFilename);
if (!outfile.open(QIODevice::WriteOnly)) {
cout << "\nFile cant opened\n";
system("pause");
return 2;
}
QByteArray bytes, bytes2;
QBitArray bits;
while ((bytes = infile.read(BUFFER_SIZE_BYTE)) >0 ) {
bits = bytesToBits(bytes);
bytes2 = bitsToBytes(bits);// PROBLEM IS HERE
outfile.write(bytes2);
}
outfile.close();
infile.close();
cout << "Finished\n";
return a.exec();
}
Initialization problem.
QByteArray bitsToBytes(QBitArray bits) {
QByteArray bytes;
bytes.resize(bits.count()/8+1);
bytes.fill(0);
// Convert from QBitArray to QByteArray
for(int b=0; b<bits.count(); ++b)
bytes[b/8] = ( bytes.at(b/8) | ((bits[b]?1:0)<<(b%8)));
return bytes;
}
this produces the right answer
QByteArray bitsToBytes(const QBitArray& bits)
{
QByteArray bytes;
QDataStream stream(&bytes, QIODevice::WriteOnly);
stream << bits;
return bytes;
}
You might also want to read about endianness from the Wikipedia http://en.wikipedia.org/wiki/Endianness
QBitArray bits(8);
// The deep copy of bits
QByteArray bytes(bits.bits(), bits.count() / 8);
--------------------------------------------------------------------------
// The bits are not copied
QByteArray bytes = QByteArray::fromRawData(bits.bits(), bits.count() / 8);
Based on answers from iloahz, solve the problem of output file size grow up 1 byte.
QByteArray bitsToBytes(QBitArray bits) {
QByteArray bytes;
bytes.resize(bits.count() / 8 + ((bits.count() % 8)? 1: 0));
bytes.fill(0x00);
// Convert from QBitArray to QByteArray
for(int b = 0; b < bits.count(); ++b)
bytes[b / 8] = (bytes.at(b / 8) | ((bits[b]? 1: 0) << (b % 8)));
return bytes;
}

Obtaining command line arguments in a Qt application

The following snippet is from a little app I wrote using the Qt framework. The idea is that the app can be run in batch mode (i.e. called by a script) or can be run interactively.
It is important therefore, that I am able to parse command line arguments in order to know which mode in which to run etc.
[Edit]
I am debugging using Qt Creator 1.3.1 on Ubuntu Karmic. The arguments are passed in the normal way (i.e. by adding them via the 'Project' settings in the Qt Creator IDE).
When I run the app, it appears that the arguments are not being passed to the application. The code below, is a snippet of my main() function.
int main(int argc, char *argv[])
{
//Q_INIT_RESOURCE(application);
try {
QApplication the_app(argc, argv);
//trying to get the arguments into a list
QStringList cmdline_args = QCoreApplication::arguments();
// Code continues ...
}
catch (const MyCustomException &e) { return 1; }
return 0;
}
[Update]
I have identified the problem - for some reason, although argc is correct, the elements of argv are empty strings.
I put this little code snippet to print out the argv items - and was horrified to see that they were all empty.
for (int i=0; i< argc; i++){
std::string s(argv[i]); //required so I can see the damn variable in the debugger
std::cout << s << std::endl;
}
Does anyone know how I can retrieve the command line args in my application?
If your argc and argv are good, I'm surprised this would be possible as QApplication::arguments() is extremely simple. Note the source code. Filtering the #ifdefs for Linux, it's just:
QStringList QCoreApplication::arguments()
{
QStringList list;
if (!self) {
qWarning("QCoreApplication::arguments: Please instantiate the QApplication object first");
return list;
}
const int ac = self->d_func()->argc;
char ** const av = self->d_func()->argv;
for (int a = 0; a < ac; ++a) {
list << QString::fromLocal8Bit(av[a]);
}
return list;
}
That's all you've got. There's a Unicode caveat which I would not think would apply to Karmic:
"On Unix, this list is built from the argc and argv parameters passed to the constructor in the main() function. The string-data in argv is interpreted using QString::fromLocal8Bit(); hence it is not possible to pass, for example, Japanese command line arguments on a system that runs in a Latin1 locale. Most modern Unix systems do not have this limitation, as they are Unicode-based."
You might try a copy of that code against your argc and argv directly and see what happens.
Only in order to keep response up-to-date, Qt now provides a dedicated class for parsing command line:
http://doc.qt.io/qt-5/qcommandlineparser.html
P.S. : can only post this as response and not a comment; I'm sorry because the question was not really how to parse but how to access.
If you are writing a Console only application then you might want to consider using QCoreApplication instead of QApplicition. QCoreApplication is part of QtCore while QApplication is defined in QtGui, so you get an extra and unnecessary dependency.
here is a simple example to have the arguments in a QStringList. Assuming you start the app with argument -q -t
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
QString x;
for (int i=1; i<argc; i++)
{
x.append(argv[i]);
}
qDebug() << x;
QStringList args = x.split("-");
args.removeFirst();
qDebug() << "args="<< args;
return a.exec();
}
Output is as follow
x= "-q-t"
args= ("q", "t")
Now you have the arguments as a QStringList ..
and here is a complete code i wrote and use in a small application
#include "mainwindow.h"
#include <QApplication>
#include <QDebug>
static QStringList arguments;
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
//analyze the arguments
//-b: use buidin player and if it does not exist use mpg123 shell to play files
//
//-t: test the player upon startup and exit
//-s: use the following speaker ID for the test
//-f: use the following file name and path
//syntax: example:
// -b : to use build in player
// -t -s xx:xx:xx:xx:xx -f azanfile.mp3: to test upon startup playing a file
bool useBuildInPlayer;
QString x;
for (int i=1; i<argc; i++)
{
x.append(argv[i]);
}
arguments << x.split("-"); arguments.removeFirst();
qDebug() << arguments;
if (arguments.indexOf("b")>=0)
useBuildInPlayer=true;
else
useBuildInPlayer=false;
bool TestSpeaker = false;
bool spkr=false; QString speaker;
bool playfile=false; QStringList testfiles;
QString filestring;
foreach (QString x, arguments)
{
if (x.left(1)=="s")
{
speaker = x.mid(1,-1); //remove the s from the beginning
spkr=true;
}
if (x.left(1)=="f")
{
filestring=x.mid(1,-1);
playfile=true;
testfiles<<filestring;
}
if (x=="t")
TestSpeaker = true;
}
if (TestSpeaker)
{
if (spkr)
{
qDebug() << "testing speaker "<< speaker;
}
else
{
qDebug() << "test argument needs speaker -s xx:xx:xx:xx:xx";
}
if (playfile)
{
qDebug() << "testing file "<< filestring;
}
else
{
qDebug() << "test file is missing";
}
}
if (TestSpeaker && spkr && playfile)
{
if (useBuildInPlayer) //use build in player
{
qDebug() << "testing using buildin player";
}
else // use mpg123 shell
{
qDebug() << "testing using mpg123 shell";
}
}
return a.exec();
}