Как предотвратить повторное открытие файла?

#c #qt #qt5

#c #qt #qt5

Вопрос:

У меня есть Mdi application .
Это приложение позволяло открывать текстовые файлы внутри subWindow .
Проблема в том, что вы можете открывать один и тот же файл много раз.

Я использовал следующий неполный код:

 QList<QMdiSubWindow*> subWindows = ui->mdiArea->subWindowList()
 

Но как я могу узнать, существует ли файл или нет.

Как я могу предотвратить такое поведение?


Модификация

Я делаю следующий код, и он работает нормально: ( Please review the code )

 QList <QMdiSubWindow*> subWindows = ui -> mdiArea -> subWindowList();
if (subWindows.count() > 0) {
    for (int i = 0; i < subWindows.count(); i  ) {
        if (subWindows.at(i) -> property("filePath").toString() == fileDlg) {
            return;
        }
    }
}
 

Полный код:

 QString fileDlg = QFileDialog::getOpenFileName(this, "Open File", "F://", "Text Files(*.txt)");
if (fileDlg != "") {

    // Start the important code
    QList < QMdiSubWindow * > subWindows = ui -> mdiArea -> subWindowList();
    if (subWindows.count() > 0) {
        for (int i = 0; i < subWindows.count(); i  ) {
            if (subWindows.at(i) -> property("filePath").toString() == fileDlg) {
                return;
            }
        }
    }
    // End the important code  

    QString cache;
    QFile file(fileDlg);
    if (file.open(QFile::ReadOnly)) {
        QTextStream in ( amp; file);
        while (!file.atEnd()) {
            cache = in .readAll();
        }
    }
    file.close();


    QFileInfo finfo(file);
    QWidget * widget = new QWidget(this);
    QTextEdit * TextEdit = new QTextEdit(widget);
    TextEdit -> setObjectName("myTextEdit");
    QMdiSubWindow * mdiWindows = ui -> mdiArea - > addSubWindow(widget);
    mdiWindows -> setProperty("filePath", fileDlg);
    mdiWindows -> setGeometry(5, 5, 300, 250);
    mdiWindows -> setWindowTitle(finfo.baseName());
    mdiWindows -> layout() -> addWidget(TextEdit);
    mdiWindows -> setWindowState(Qt::WindowMaximized);
    mdiWindows -> layout() -> setSpacing(0);
    TextEdit -> setText(cache);
    mdiWindows -> show();
}
 

Комментарии:

1. используйте контейнер для ведения списка открытых файлов, при открытии нового файла проверьте, есть ли открываемый файл в списке открытых файлов.

2. Спасибо, но можно ли привести мне пример?

Ответ №1:

В зависимости от операционной системы один и тот же файл может иметь несколько разных имен. Даже на одно и то же имя можно ссылаться по-разному (подумайте о том, чтобы обойти структуру каталогов!). Любая схема, основанная исключительно на именах, обречена на провал.

Это часто бывает даже весьма полезно, я часто открываю один и тот же файл несколько раз, чтобы просмотреть одно место при редактировании другого. Пусть пользователь решает.

Ответ №2:

Пример кода по мере необходимости:

 class MdiWindow 
{
    static std::vector<std::wstring> s_filePaths;
    bool openNewFile(const std::wstringamp; filePath) {
        std::vector<std::wstring>::iterator iter = std::find(s_filePaths.begin(), s_filePaths.end(), filePath);
        //already opened
        if (iter != s_filePaths.end()) {
            return true;
        }
        if (openFileSucceeded(filePath)) {
            s_filePaths.push_back(filePath);
            return true;
        }
        return false;
    }
    void closeFile(const std::wstringamp; filePath) {
        s_filePaths.erase(s_filePaths.begin(), std::remove(s_filePaths.begin(), s_filePaths.end(), filePath));
    }
}
 

Ответ №3:

Простого способа сделать это нет. Он имеет зависящие от платформы решения, запрашивая структуры данных ядра и просматривая структуры для каждого процесса, что непросто.

Но вы можете открывать файлы своим приложением в контейнере и проверять его значения при открытии нового файла.

Контейнер может быть членом класса, например :

 QList<QString> openedFileNames;
 

Открытие файла :

 if(!openedFileNames.contains(filename))
{
    openedFileNames.append(filename);

    QFile file( filename );

    if( !file.open( QIODevice::ReadOnly | QIODevice::Text ) )
        QMessageBox::warning(this, tr("Error opening!"), tr("Could not open the file"));

    ...
}
 

Закрытие файла :

 openedFileNames.removeAt(openedFileNames.indexOf(filename));
file.close();
 

Комментарии:

1. Спасибо вам, мистер @Nejat , за помощь, я решил эту проблему. пожалуйста, просмотрите мой код, чтобы узнать, хороший он или плохой. посмотрите на мой вопрос еще раз, который я обновил.

Ответ №4:

После первого открытия используйте:

http://doc.qt.io/qt-5/qlockfile.html

В вашем коде добавьте:

 QFile file(fileDlg);
if (file.open(QFile::ReadOnly)) {
    QTextStream in ( amp; file);
    while (!file.atEnd()) {
        cache = in .readAll();
    }
} else {
    //Something...
    return;
}
file.close();
 

Комментарии:

1. Спасибо, но как использовать QLockFile class. Я сделал QLockFile lockFile(fileDlg); lockFile.lock(); .

2. @LionKing к сожалению, я не могу заблокировать чтение. Я попробую еще раз завтра.