PDA

View Full Version : Erasing the content of a txt file



Momergil
29th July 2011, 19:09
Hello!

I'm trying to create a function in my software that creates new txt files with increasing number each time a new file must be created.

In other words, normally we would use a simple variable (int) that would be increased each time a new txt file must be created, and that would be read each time to see the new name. But the problem is that the software may be shut down, and when startet again, the int variable would be set to zero once again instead of continuing from the last number.

The algorithm I decided to create is this: the software opens a different txt file "TxtNumber" with a given number on it (in the beginning, 0). It reads than that number, put it in a variable and add +1 (so the first txt will be "Text number 1"). Than it erases the TxtNumber and write on it the new number (1). And from that it moves one.

If the software is shut down and open again, when it reads the "TxtNumber", it will read "1", add +1, erase and write "2" in it.


The problem is that I couldn't find a function that can erase the txt file (before I write the new number on it) or, given the fact that just one line will be used, erase one line. Is there such function?


Thanks!

cincirin
29th July 2011, 19:43
You can simply QIODevice::seek (http://doc.qt.nokia.com/latest/qiodevice.html#seek) after you read the integer variable.

Momergil
29th July 2011, 20:07
You can simply QIODevice::seek (http://doc.qt.nokia.com/latest/qiodevice.html#seek) after you read the integer variable.

Sorry, I didn't understand how to do that. Could you please be a little bit more descriptive? (e.g. with a code?)

Tanks!

mvuori
29th July 2011, 20:44
Actually, you probably should -- instead of raw reading and writing files -- use QSettings, which is a class well suited to keeping track of such information, including any metadata related to the files.

cincirin
29th July 2011, 21:19
If you don't read/write any other informations in file, then, as @mvuori said, QSettings (http://doc.qt.nokia.com/stable/qsettings.html) is what you should looking for.
Else if you want to use a particular file, before you read the integer variable, you can find the position in file with QIODevice :: pos (http://doc.qt.nokia.com/stable/qiodevice.html#pos). After you read a integer variable from file, increment it, and call seek() (http://doc.qt.nokia.com/stable/qiodevice.html#seek) with position that you have found. Now you can write new incremented variable. Note, that this will be working if you open the file in binary mode.

SixDegrees
31st July 2011, 11:39
I would not recommend storing the count separately; the potential for things to get out of sync is non-zero, and if the external count is ever lost, you can't recover.

I'd simply store the count as the first item in the file. Set aside 4 bytes at position 0 and write a binary unsigned integer to it. Or set aside, say, 10 bytes and store the ASCII representation of an integer there. Retrieve when the file is next read, and update as required, which only needs a seek(0) and a read() or write(). The contents that follow are exactly the same as before, but offset by the length of the header. Everything is now self-contained.

DanH
31st July 2011, 16:02
If you really need to keep a count like this, vs just using one of the "find an unused file name" schemes, use a SQL database. Overkill, I know, for such a simple function, but simple and reliable to accomplish.

Momergil
2nd August 2011, 16:10
Hello!

First, thanks for the help. In fact I was able to find a solution to the problem without having to ask for any "delete txt" function, despite I still don't know exactly what Qt is thinking when it does so with the code I implemented. Here it is:


void myclient::definetxtpath()
{
v_txtdirectory = new QDir;
v_txtdirectoryname = "./LifeshockGraph";
if (!v_txtdirectory->exists(v_txtdirectoryname))
{
v_txtdirectory->mkpath(v_txtdirectoryname);
Filenumber = "./LifeshockGraph/ECGnumber.txt";
}
else
{
Filenumber = "./LifeshockGraph/ECGnumber.txt";
}
}

void myclient::definetxttitle()
{
mFileN.setFileName(Filenumber);
if (!mFileN.exists())
{
//Write initial number
if(!mFileN.open(QFile::WriteOnly | QFile::Text))
{
qDebug() << "Could not open number file for writing initial number.";
pmw->ui->cmd->append("Could not open number file for writing initial number");
return;
}
else
{
outN = new QTextStream(&mFileN);
*outN << v_currentnumber; //Escreve "0".
mFileN.flush();
mFileN.close();
}
}

//Read previous ECG number
mFileN.setFileName(Filenumber);
if(!mFileN.open(QFile::ReadOnly | QFile::Text))
{
qDebug() << "Could not open number file for reading previous number.";
pmw->ui->cmd->append("Could not open number file for reading previous number");
v_currentdatetimeFailure = true;
return;
}
else
{
inN = new QTextStream(&mFileN);
v_readint = inN->readLine();

v_currentnumber = v_readint.toInt();
v_newnumber = v_currentnumber + 1;

mFileN.flush();
mFileN.close();

//Write new ECG number
mFileN.setFileName(Filenumber);
if(!mFileN.open(QFile::WriteOnly | QFile::Text))
{
qDebug() << "Could not open number file for writing.";
pmw->ui->cmd->append("Could not open number file for writing");
return;
}
else if (v_currentdatetimeFailure==false) //Se ele conseguiu ler o número anterior, escreve o novo número.
{
outN = new QTextStream(&mFileN);
*outN << v_newnumber;
}
else //Se tiver houvido erro na hora de ler o número anterior do ECG, dá erro.
{
qDebug() << "Complete failure in reading the ECG number.";
pmw->ui->cmd->append("Complete failure in reading the ECG number");
}
}

mFileN.flush();
mFileN.close();

Filename = "./LifeshockGraph/ECGtransmission.txt";

//Set txt title
mFile.setFileName(Filename);
if(!mFile.open(QFile::WriteOnly | QFile::Text))
{
qDebug() << "Could not open file for writing.";
pmw->ui->cmd->append("Could not open file for writing");
return;
}
else
{
out = new QTextStream(&mFile);

v_currentdatetime = QDateTime::currentDateTime();
if (v_currentdatetimeFailure==false) *out << "Socket connection number " << v_newnumber << ".\n";
else *out << "Failed to pick ECG transmission number.\n";
*out << v_currentdatetime.toString("dd-MM-yyyy hh:mm:ss") << ".\n\n";
}
}

Quite a giant code...

By the other hand, I possibly will one day improve my code and try the ways you showed to me, so I'still glad for the information.

Lots of thanks.

Martin/Momergil