Issue with deleting text in file - c++

Explaining of my purpose:
my program have two section first reading two word from user(second word is meaning of first one) and save this words in two text file second section is showing or deleting words as desire of user.
What is my issue?:
my program works perfectly but after days will something like this happen:
when i try to delete two words from .txt files(i mean 1 word with meaning of it) first word will delete but second word(meaning) will not delete, it sounds like .txt file corrupted only thing that will fix every thing is delete that text file and create new one and thats very annoying that means lose all informations
note: first word and second word are in separate files. second words are still able to show.
what did i try?:
i try to check that is second word text file open or closed. that sounds like it will open or close in right time.
check that if text file is read-only. that wasnt.
i dont know what really happening here :( !!!!
here its my delete code am i missing something ?
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <fstream>
#include <QFile>
#include <QTextStream>
#include <QIODevice>
#include <QDebug>
#include <QMessageBox>
#include <QProcess>
#include <iostream>
#include <string>
#include <unistd.h>
using namespace std;
void newFunc();
void restartApp();
void makeFa();
int xy=-1;
ifstream sfile("en.txt");
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
newFunc();
ui->setupUi(this);
}
MainWindow::~MainWindow()
{
delete ui;
}
void newFunc(){
QFile check("EnTemp.txt");
if(check.exists()){
}
else{
ofstream EnTemp("EnTemp.txt");
}
}
void restartApp()
{
qApp->quit();
QProcess::startDetached(qApp->arguments()[0], qApp->arguments());
}
void MainWindow::on_Enter_clicked()
{
if((ui->InEN->text().isEmpty()) || (ui->InFa->text().isEmpty())){
QMessageBox msg;
msg.setText("Fields are empty");
msg.exec();
}
else{
QString en,fa;
en=ui->InEN->text();
fa=ui->InFa->text();
// saving EN words
QFile dataE("en.txt");
dataE.open(QIODevice::WriteOnly | QIODevice::Append);
QTextStream streamE(&dataE);
streamE<<en<<"\r\n";
dataE.close();
// saving FA words
QFile DataF("fa.txt");
DataF.open(QIODevice::WriteOnly | QIODevice::Append);
QTextStream streamF(&DataF);
streamF.setCodec("UTF-8");
streamF<<fa<<"\r\n";
DataF.close();
ui->InEN->clear();
ui->InFa->clear();
}
}
void MainWindow::on_Next_clicked()
{
QFile EnTemp("EnTemp.txt");
EnTemp.open(QIODevice::WriteOnly);
QTextStream GetTemp(&EnTemp);
if(!sfile.eof()){
string get;
getline(sfile,get);
ui->ShowEn->setText(QString::fromStdString(get));
ui->ShowFa->clear();
xy++;
GetTemp<<xy;
EnTemp.close();
}
else{
restartApp();
}
}
void MainWindow::on_mean_clicked()
{
cout<<xy;
QFile openFa("fa.txt");
QString getFa;
openFa.open(QIODevice::ReadWrite);
QTextStream pointfa(&openFa);
pointfa.setCodec("UTF-8");
int forword=0;
while(forword<=xy){
getFa=pointfa.readLine();
forword++;
}
ui->ShowFa->setText(getFa);
openFa.close();
}
void MainWindow::on_delete_2_clicked()
{
makeFa();
ofstream tempE;
if(!ui->ShowEn->text().isEmpty() | !ui->ShowFa->text().isEmpty())
{
QMessageBox msg;
int ret;
msg.setText("Are you sure you want to delete this words?");
msg.setStandardButtons(QMessageBox::Yes | QMessageBox::No);
msg.setIcon(QMessageBox::Warning);
ret= msg.exec();
switch(ret){
case QMessageBox::Yes:
QString input;
input=ui->ShowEn->text();
string line;
ifstream DataE;
DataE.open("en.txt");
tempE.open("tempE.txt");
while(getline(DataE,line)){
if(line != input.toStdString()){
tempE<<line<<"\r\n";
}
}
QString inputF;
inputF= ui->ShowFa->text();
string lineF;
ifstream DataF;
ofstream tempF("tempF.txt");
DataF.open("fa.txt");
while(getline(DataF, lineF)){
if( lineF != inputF.toStdString()){
tempF<<lineF<<"\r\n";
}
}
DataE.close();
DataF.close();
tempE.close();
tempF.close();
sfile.close();
remove("en.txt");
remove("fa.txt");
rename("tempE.txt", "en.txt");
rename("tempF.txt", "fa.txt");
break;
}
}
else{
QMessageBox mass;
mass.setText("Fields are empty");
mass.exec();
}
restartApp();
}
void MainWindow::on_Restore_clicked()
{
xy= 0;
int reach=0;
string get;
QString s;
ifstream openTemp("EnTemp.txt");
openTemp>>xy;
while(reach<=xy){
getline(sfile,get);
reach++;
}
ui->ShowEn->setText(QString::fromStdString(get));
}
void makeFa(){
QFile tempF;
tempF.setFileName("tempF.txt");
tempF.open(QIODevice::ReadWrite | QIODevice::Append);
QTextStream stream(&tempF);
stream.setCodec("UTF-8");
tempF.close();
}
I'm on windows 8.1
i notice something new right now when i try to delete all information in second .txt file the size of file will be 3 bytes instead of 0 bytes

3 bytes for an otherwise empty file might match the UTF-8 BOM (not saying it is without knowing said bytes, but it is a strong hint). Your delete function might be fine (althought you should make the file filtering another function for clarity, and DRY), but would work only with ascii charset since you're relying on std::i/ofstream and std::string.
It might be (again, no certitude, just a wild guess) that you're creating a file with QFile, and that you put a "meaning" containing non-ascii characters and thus QFile automatically converts the file to an UTF-8 prefixed with BOM.
Would you mind updating your post with the file creation/update methods if you're uncertain of this lead?
[Edit] The other option would be that you're writing non ascii characters with ofstream which would probably lead to the "meaning" not being found, and thus the file being fully replicated.

Related

Qt C++ saving a image to a specified folder [duplicate]

It's strange, I add desired file into the resources via Add Existing Files..., the file is there. I run qmake ("Build->Run qmake") to make the file available.
The first issue: I can't write anything into the file from output terminal! But when I manually write into the file, the output terminal shows the change every time I run it. Second issue: it still says QIODevice::read: device not open !
Here's my code:
#include <QCoreApplication>
#include <QDebug>
#include <QFile>
#include <QString>
#include <QTextStream>
#include <iostream>
void wFile(QString Filename)
{
QFile nFile(Filename);
QTextStream str(&nFile);
qDebug() << "what do you want to write in the desired file: ";
str.readLine();
if (!nFile.open(QFile::WriteOnly | QFile::Text))
{
qDebug() << "could not open the file";
return;
}
nFile.flush();
nFile.close();
}
void read (QString Filename){
QFile nFile(Filename);
if(!nFile.open(QFile::ReadOnly | QFile::Text))
{
qDebug() << "could not open file for reading";
return;
}
QTextStream in(&nFile);
QString nText = in.readAll();
qDebug() << nText;
nFile.close();
}
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
QString nFilename =":/MyFiles/DocumentArminV.txt";
wFile(nFilename);
read(nFilename);
return a.exec();
}
And here's output terminal of the code:
The files saved in a qresource are read-only since they are part of the executable so you can not write or modify them.
docs:
Currently, Qt always stores the data directly in the executable, even on Windows, macOS, and iOS, where the operating system provides native support for resources. ...

Qt, C++ - Editing an existing INI file from project doesn't work when I need to save it [duplicate]

It's strange, I add desired file into the resources via Add Existing Files..., the file is there. I run qmake ("Build->Run qmake") to make the file available.
The first issue: I can't write anything into the file from output terminal! But when I manually write into the file, the output terminal shows the change every time I run it. Second issue: it still says QIODevice::read: device not open !
Here's my code:
#include <QCoreApplication>
#include <QDebug>
#include <QFile>
#include <QString>
#include <QTextStream>
#include <iostream>
void wFile(QString Filename)
{
QFile nFile(Filename);
QTextStream str(&nFile);
qDebug() << "what do you want to write in the desired file: ";
str.readLine();
if (!nFile.open(QFile::WriteOnly | QFile::Text))
{
qDebug() << "could not open the file";
return;
}
nFile.flush();
nFile.close();
}
void read (QString Filename){
QFile nFile(Filename);
if(!nFile.open(QFile::ReadOnly | QFile::Text))
{
qDebug() << "could not open file for reading";
return;
}
QTextStream in(&nFile);
QString nText = in.readAll();
qDebug() << nText;
nFile.close();
}
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
QString nFilename =":/MyFiles/DocumentArminV.txt";
wFile(nFilename);
read(nFilename);
return a.exec();
}
And here's output terminal of the code:
The files saved in a qresource are read-only since they are part of the executable so you can not write or modify them.
docs:
Currently, Qt always stores the data directly in the executable, even on Windows, macOS, and iOS, where the operating system provides native support for resources. ...

How to write into .ini file using Qt C++? [duplicate]

It's strange, I add desired file into the resources via Add Existing Files..., the file is there. I run qmake ("Build->Run qmake") to make the file available.
The first issue: I can't write anything into the file from output terminal! But when I manually write into the file, the output terminal shows the change every time I run it. Second issue: it still says QIODevice::read: device not open !
Here's my code:
#include <QCoreApplication>
#include <QDebug>
#include <QFile>
#include <QString>
#include <QTextStream>
#include <iostream>
void wFile(QString Filename)
{
QFile nFile(Filename);
QTextStream str(&nFile);
qDebug() << "what do you want to write in the desired file: ";
str.readLine();
if (!nFile.open(QFile::WriteOnly | QFile::Text))
{
qDebug() << "could not open the file";
return;
}
nFile.flush();
nFile.close();
}
void read (QString Filename){
QFile nFile(Filename);
if(!nFile.open(QFile::ReadOnly | QFile::Text))
{
qDebug() << "could not open file for reading";
return;
}
QTextStream in(&nFile);
QString nText = in.readAll();
qDebug() << nText;
nFile.close();
}
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
QString nFilename =":/MyFiles/DocumentArminV.txt";
wFile(nFilename);
read(nFilename);
return a.exec();
}
And here's output terminal of the code:
The files saved in a qresource are read-only since they are part of the executable so you can not write or modify them.
docs:
Currently, Qt always stores the data directly in the executable, even on Windows, macOS, and iOS, where the operating system provides native support for resources. ...

Why QXmlQuery seem to add a ` \n` to results? (and how to solve it?)

Writing a little code to extract some values from an XML, the result of the XPath seem to add \n after the content.
#include <QCoreApplication>
#include <QXmlQuery>
#include <QString>
#include <QDebug>
auto main(int argn, char* argc[])->int
{
QCoreApplication app(argn, argc);
QString replyContent="<Root isOk='ok'/>";
QXmlQuery query;
query.setFocus(replyContent);
query.setQuery("string(//#isOk)");
// Attribute seem to add \n
QString queryResult;
if (query.evaluateTo(&queryResult))
{
qDebug() << queryResult; // Where this \n come from?
qDebug() << queryResult.size(); // Why 3? shouldn't be 2?
}
}
Expected result:
"ok"
2
Given result:
"ok\n"
3
This obviously has some side effects which I would like to avoid.
Why is this \n added? And how to solve it?
I think that this is introduced by the QXmlFormatter that is used when serialising the results to a QString; I suspect that QXmlFormatter::endDocument writes a newline.
One workaround would be to output to a string list instead, then pick the first element:
QStringList results;
if (query.evaluateTo(&results))
{
const QString& queryResult = results.first();
qDebug() << queryResult;
qDebug() << queryResult.size();
}
You might choose to join() the results instead, if you need them all.
Alternatively you can take full control of the serialization and use either QXmlSerializer or QXmlFormatter. That way you will have in the output whatever you ask, not some defaults you are provided with. It will have more code, that's true but the intent will be clearer than just discarding some newline at the end.
Here is an example of how to do it with QXmlSerializer (which produces no redundant symbols by default):
#include <QCoreApplication>
#include <QXmlQuery>
#include <QXmlSerializer>
#include <QString>
#include <QBuffer>
#include <QDebug>
auto main(int argn, char* argc[])->int
{
QCoreApplication app(argn, argc);
QString replyContent="<Root isOk='ok'/>";
QXmlQuery query;
query.setFocus(replyContent);
query.setQuery("string(//#isOk)");
QBuffer buffer;
buffer.open(QBuffer::ReadWrite);
QXmlSerializer serializer(query, &buffer);
if (query.evaluateTo(&serializer))
{
QString queryResult = QString::fromUtf8(buffer.buffer());
qDebug() << queryResult;
qDebug() << queryResult.size();
}
}

QClipboard cannot get clipboard data if copied from Notepad/Chrome

In my program, my users can copy a string of text from anywhere and paste it into my program. I use the simple QApplication::clipboard()->text(); function and everything works as expected. However, several of my users are having problems when trying to copy and paste on Windows 8.1
Here is how I access the clipboard text from my paste function:
QString clipboard = QApplication::clipboard()->text();
//check if the clipboard is empty
if(QApplication::clipboard()->text().isEmpty())
return;
//do something with clipboard
But if the text was copied from Notepad or Chrome, the text is ALWAYS empty. Windows 7 users have not had any problems. Not ALL Windows 8 users have this issue, it's only a handful but the issue it consistent. When copied from some other random places or within my program itself, the clipboard works fine.
I've tried using mimeData. When using the function formats(), only plain text is an available format, but the text is always empty.
The text being copied from Notepad/Chrome shows up fine in clipboard viewers and stuff and can be pasted elsewhere in other programs.
Copying and pasting is a very important feature in my program and its frustrating that my users can't copy and paste from Notepad or Chrome.
Any ideas? Thanks for your time. :)
EDIT: I tried using the "windows" style technique. There was no change. Here is my current, still unworking code:
QString clipboard = QApplication::clipboard()->text();
//check if the clipboard is empty
if(clipboard.isEmpty())
{
//might not actually be empty. Check using the other technique
if (IsClipboardFormatAvailable(CF_TEXT) && OpenClipboard(NULL))
{
HGLOBAL hGlobal = GetClipboardData(CF_TEXT) ;//hGlobal is NULL
if (hGlobal != NULL)//This never gets called because it is NULL
{
LPTSTR lpszData = (LPTSTR) GlobalLock(hGlobal) ;
if (lpszData != NULL)
{
clipboard.fromLocal8Bit((const char *)lpszData);
GlobalUnlock(hGlobal) ;
}
}
CloseClipboard() ;
}
if(clipboard.isEmpty())
return;
}
The copied text shows up fine in a clipboard viewer, but my program can't get to it no matter what:
How come GetClipboardData() isn't picking anything up? Again, the copied text CAN be pasted in any other program I've tried... just not mine. But if copied from somewhere else, it works no problem.
EDIT: With this version, When the user copies text and text gets to clipboard, a function copies the text this time to an internal text file not directly to your program, using QFile. Another function copies the text from the internal text file to your program. By this way, i think your program wouldn't have to directly deal with text in the clipboard
clipboard.h
#ifndef CLIPBOARD_H
#define CLIPBOARD_H
#include <QDialog>
#include <QClipboard>
#include <QLabel>
#include <QHBoxLayout>
#include <QTextEdit>
#include <QPushButton>
#include <QFile>
#include <QTextStream>
class ClipBoard : public QDialog {
Q_OBJECT
public:
explicit ClipBoard(QWidget *parent = 0);
~ClipBoard();
private slots:
//the functions that will copy and paste text from the text file
void copyToTextFile();
void paste();
private:
QPushButton *button;
QTextEdit *edit;
QString textFromClipBoard;
QClipboard *clipBoardText;
QString clipboard;
};
#endif // CLIPBOARD_H
clipboard.cpp
#include "clipboard.h"
#include "ui_clipboard.h"
ClipBoard::ClipBoard(QWidget *parent) : QDialog(parent) {
button = new QPushButton("&Paste Copied Text");
edit = new QTextEdit;
/*when user copies text and text gets to clipboard, the text is copied
from clipboard to a text file then copied from the text file to the
program*/
connect(button, SIGNAL(clicked()), this, SLOT(copyToNotepad()));
connect(button, SIGNAL(clicked()), this, SLOT(paste()));
QVBoxLayout *layout = new QVBoxLayout;
layout->addWidget(button);
layout->addWidget(edit);
setLayout(layout);
}
/*This function copies text from the clipboard to an internal text file
created by the program*/
void ClipBoard::copyToTextFile() {
clipboard = QApplication::clipboard()->text();
QFile output("out.txt");
if (output.open(QIODevice::ReadWrite | QFile::Truncate |
QIODevice::Text)) {
QTextStream out(&output);
out << clipboard;
}
}
/*This function then copies the text from the internal text file and pastes
it to the text edit. So the program doesn't have to deal directly with the
clipboard*/
void ClipBoard::paste() {
QFile input("out.txt");
if (input.exists()) {
if (input.open(QIODevice::ReadOnly | QIODevice::Text)) {
QTextStream in(&input);
clipboard = in.readAll();
}
}
edit->setText(clipboard);
}
ClipBoard::~ClipBoard() {
}
main.cpp
#include "clipboard.h"
#include <QApplication>
int main(int argc, char *argv[]) {
QApplication a(argc, argv);
ClipBoard w;
w.show();
return a.exec();
}
Look through and compare with your part of the code to see if there's something you did wrong. But as to how you claim it works on some Windows 8.1 systems and don't on others baffles me.
I had similar issue,
the solution for me is sleep.
void MainWindow::on_clipboard_change(){
QThread::msleep(1); //without this line I get allways empty clipboard
QString text = QGuiApplication::clipboard()->text();
qDebug() << "clipboard change event triggered ( " << text << " )";
}