0
votes

I am working on a project for an assignment and I need some help with QFile and QTextStream. I want to initially create a File (named: users.txt) that has this inside of it:

ID   Password    Name and Surname   Username
1    |  cheese    |  Daniel Markov  |  MaDanjel
2    |  something |  Mika Firring   |  Marila
..
..

So far I get the following contents of skrivno.txt:

0202|Nejc Zun|nejczun|

This is the code:

void registracija::write() {
    QFile username("skrivno.txt");
    if(!username.open(QIODevice::Append))
        QMessageBox::information(0,"Error",username.errorString());
     QTextStream u1(&username);
     username.open(QIODevice::Append | QFile::Text);
     u1 << ui->lineEdit_3->text()+"|"; //code
     u1 << ui->lineEdit_4->text()+"|"; //name and surname
     u1 << ui->lineEdit_5->text()+'\n'; //password
     username.close();
}

My plan was to than call the text from this function:

void MainWindow::on_pushButton_3_clicked()//login
{
    QFile username("skrivno.txt");
    if(!username.open(QIODevice::ReadOnly))
        QMessageBox::information(0,"Error",username.errorString());
    QTextStream u1(&username);
    username.open(QIODevice::ReadOnly | QFile::Text);
    QString temp;
    while (!u1.atEnd()) {
        temp = u1.readLine();
        if((ui->lineEdit_2->text()== temp.section("|",0,0)) && (ui->lineEdit->text()== temp.section("|",2,2))){
            ui->label_2->setText("Welcome: " + temp.section("|",1,1));
            ui->progressBar->show();
            for(int a=0;a<101;a++){
                ui->progressBar->setValue(a);
            }
            Open_Window();
            ui->progressBar->close();
            ui->un1->close();
            ui->un2->close();
            ui->label_3->close();
            player->stop();
        }else{
            ui->label->close();
            ui->un1->show();
            ui->un2->show();
            ui->label_3->show();
            player->stop();
        }
    }
    username.close();
}

And that it could be able to read from different users so it checks the users Username and Password, if it's the correct user with the correct password it let's him open the things below.

This is the code that tests only the 1st line of the File skrivno.txt

if((ui->lineEdit_2->text()== temp.section("|",0,0)) && (ui->lineEdit->text()== temp.section("|",2,2)))

And now I need help with this so not only does it write the ID in the text, but also checks all the users and their passwords if they are the correct ones, not only the first one in the file.


My code works. I need help improving the code by:

  • adding the ID in the text file (I dont know how to add it by 1 every time someone registers a new user.
  • checking every user and their password (not only the first one)

Something like this:

void registracija::write() {
        QFile username("skrivno.txt");
        if(!username.open(QIODevice::Append))
            QMessageBox::information(0,"Error",username.errorString());
         QTextStream u1(&username);
         username.open(QIODevice::Append | QFile::Text);
         u1 << SOMEHOW ADD THE ID IN HERE AND ALWAYS ADD IT +1 // <= help needed
         u1 << ui->lineEdit_3->text()+"|"; //code
         u1 << ui->lineEdit_4->text()+"|"; //name and surname
         u1 << ui->lineEdit_5->text()+'\n'; //password
         username.close();
    }
1
I want to read from a text file (this is the link of how I imagine it - prntscr.com/as94mm) and than test if the the user that is logging in is in the text file and test if he has the correct password like in the code aboveSir Rage
I would reconsider this approach. Each line represents a user so I would create a Class User out of it. And than you can read all user in and save them in a List or Map or even better a Class that will handle the users. The way you do it right now can lead to registrations with the same username. A surrounding Class could also remember the highest ID that a user had and than it wouldn't be a problem to increment it by one, if you add a new User.0rko

1 Answers

1
votes

Maybe this approach will fit your need :)

class User;
QDebug       operator<< (QDebug d, const User &user);
QTextStream& operator<< (QTextStream& os, const User& user);


class User
{
public:
    User();
    User(QString data);

    bool setData(const QString &data);

    int id() const                              { return m_id; }
    void setId(int id)                          { m_id = id; }

    QString username() const                    { return m_username; }
    void setUserName(const QString &username)   { m_username = username; }

    QString name()      const                   { return m_name; }
    void setName(const QString &name)           { m_name = name; }

    QString password()  const                   { return m_password; }
    void setPassword(const QString &password)   { m_password = password; }

private:
    int m_id;
    QString m_username;
    QString m_name;
    QString m_password;
};

-

QDebug operator<<(QDebug d, const User &user) {
    QStringList data;
    data << QString::number(user.id());
    data << user.username();
    data << user.name();
    data << user.password();
    return d << data.join("|");
}

QTextStream& operator<< (QTextStream& os, const User& user){
    QStringList data;
    data << QString::number(user.id());
    data << user.username();
    data << user.name();
    data << user.password();
    return os << data.join("|") << "\n";
}


User::User()
{

}


User::User(QString data)
{
    setData(data);
}


bool User::setData(const QString &data)
{
    QStringList splittedData = data.split("|");
    m_id        = splittedData.value(0).toInt();
    m_password  = splittedData.value(1).trimmed();
    m_name      = splittedData.value(2).trimmed();
    m_username  = splittedData.value(3).trimmed();
    return true;
}

-

class UserManager
{
public:
    UserManager();

    bool readUsers(const QString &fileName);
    bool writeUsers(const QString &fileName);

    bool userExists(const QString &username) const;
    bool addUser(const QString &username, const QString &name, const QString &password);
    bool checkPassword(QString username, QString password) const;
    int lastId() const;

private:
    QMap<QString, User*> m_users;
    int m_lastId;
};

-

bool lessThan(User* u1, User* u2){
    return u1->id() < u2->id();
}

UserManager::UserManager()
{
    m_lastId = 0;
}

bool UserManager::readUsers(const QString &fileName)
{
    QFile file(fileName);
    if (!file.exists()){
        qDebug() << QString("Error: File not found: '%1'").arg(fileName);
        return false;
    }

    if (file.open(QIODevice::ReadOnly)){
        QTextStream stream(&file);
        stream.readLine(); // drop header
        while (!stream.atEnd()){
            QString data = stream.readLine();
            User *user = new User();
            user->setData(data);
            m_lastId = (user->id() > m_lastId) ? user->id() : m_lastId;
            m_users.insert(user->username(), user);
        }
        return true;
    } else {
        qDebug() << QString("Error: Could not open file '%1'").arg(fileName);
    }
    return false;
}


bool UserManager::writeUsers(const QString &fileName)
{
    QFile file(fileName);
    QList<User*> list = m_users.values();
    qSort(list.begin(), list.end(), lessThan);
    if (file.open(QIODevice::WriteOnly)){
        QTextStream stream(&file);
        foreach(User *user, list){
            stream << *user;
        }
        return true;
    } else {
        qDebug() << QString("Error: Could not open file '%1'").arg(fileName);
    }
    return false;
}


bool UserManager::userExists(const QString &username) const
{
    return m_users.keys().contains(username);
}


bool UserManager::addUser(const QString &userName, const QString &name, const QString &password)
{
    if (m_users.contains(userName)){
        qDebug() << QString("User '%1' already exists").arg(userName);
        return false;
    }

    User *user = new User;
    user->setId(++m_lastId);
    user->setUserName(userName);
    user->setName(name);
    user->setPassword(password);
    m_users.insert(userName, user);
    return true;
}


bool UserManager::checkPassword(QString username, QString password) const
{
    if (m_users.keys().contains(username)){
        return m_users.value(username)->password() == password;
    }
    return false;
}

int UserManager::lastId() const
{
    return m_lastId;
}