Там же несколько проблем:
У вас есть как C++ и Qt, используйте QFile
, не используйте обнаженных файлы C!
qString1
является бедной копией str
, так что в этом смысл?
Копирование файлов по символам выполняется довольно плохо.
Вы не хотите блокировать свой графический интерфейс при выполнении файловых операций в целом. Они должны выполняться в отдельном потоке.
Ниже приведен пример того, как это можно сделать. Я стремился полностью использовать то, что Qt может предложить, сохраняя при этом QWidget-based. Это автономный пример с одним файлом, просто добавьте его как одиночный файл в проект qt guy в Qt Creator, а затем создайте и запустите. Помните, что этот код откроет файлы в текущем рабочем каталоге!
Стоимость использования другой темы с точки зрения сложности кода составляет буквально 6 строк. Если вы не хотите использовать отдельный поток доступа к файлу и все в порядке, когда ваш пользовательский интерфейс блокируется потенциально медленными файлами в сети и т. Д., То следующие 6 строк могут быть удалены без каких-либо изменений кода. Это красота Qt.
QThread * m_thread;
w->moveToThread(m_thread);
m_thread(new QThread(this)),
m_thread->start();
m_thread->exit();
m_thread->wait();
без резьбы в месте, вы можете также заменить QMetaObject::invokeMethod(w, "joinFiles");
с более простой w->joinFiles()
. Причиной использования invokeMethod
вместо прямого вызова является вызов слота в потоке, в котором выполняется объект. invokeMethod
, за кулисами, отправит QMetaCallEvent
рабочему объекту. Это событие будет подхвачено контуром событий, запущенным в потоке, и вызовет звонок для рабочего слота joinFiles
, , выполненного в правильной нити - worker->thread()
.
Обратите внимание, что я не получаю от QThread
и что для всех операций с файлами используется только один поток. Это вполне адекватно, если ваша отправная точка состоит в том, чтобы все обращения к файлам выполнялись в потоке графического интерфейса пользователя. Таким образом, есть два потока: один, который имеет только GUI, а другой, который только выполняет сериализованный доступ к файлам.

#include <QWidget>
#include <QPushButton>
#include <QPlainTextEdit>
#include <QLineEdit>
#include <QSpinBox>
#include <QLabel>
#include <QFormLayout>
#include <QMetaObject>
#include <QFile>
#include <QDir>
#include <QThread>
#include <QApplication>
class Worker : public QObject {
Q_OBJECT
Q_PROPERTY(int fileIndex READ fileIndex WRITE setFileIndex)
Q_PROPERTY(QString sourceFileName READ sourceFileName)
Q_PROPERTY(QString targetFileName READ targetFileName WRITE setTargetFileName)
int m_fileIndex;
QString m_targetFileName;
public:
Worker(int fileIndex, QString targetFileName, QObject * parent = 0) :
QObject(parent), m_fileIndex(fileIndex), m_targetFileName(targetFileName) {}
explicit Worker(QObject * parent = 0) : QObject(parent), m_fileIndex(0) {}
Q_SIGNAL void filesJoined(bool OK);
Q_SLOT void joinFiles() {
QFile src(sourceFileName());
QFile dst(m_targetFileName);
if (! src.open(QIODevice::ReadOnly)
|| ! dst.open(QIODevice::Append))
{
emit filesJoined(false);
return;
}
while (! src.atEnd()) {
dst.write(src.read(16384));
}
emit filesJoined(true);
}
int fileIndex() const { return m_fileIndex; }
void setFileIndex(int i) { m_fileIndex = i; }
QString sourceFileName() const { return QString("test%1.txt").arg(m_fileIndex); }
QString targetFileName() const { return m_targetFileName; }
void setTargetFileName(const QString & n) { m_targetFileName = n; }
};
class Window : public QWidget {
Q_OBJECT
QThread * m_thread;
QSpinBox * m_index;
QLineEdit * m_target;
QPlainTextEdit * m_log;
Q_SLOT void on_pushButton_clicked() {
Worker * w = new Worker;
w->setFileIndex(m_index->value());
w->setTargetFileName(m_target->text());
w->moveToThread(m_thread);
connect(w, SIGNAL(filesJoined(bool)), SLOT(onJoined(bool)));
QMetaObject::invokeMethod(w, "joinFiles");
}
Q_SLOT void onJoined(bool ok) {
const Worker * w = qobject_cast<const Worker*>(sender());
m_log->appendPlainText(QString("%1 %2 to %3")
.arg(ok ? "Successfully joined" : "Couldn't join")
.arg(w->sourceFileName()).arg(w->targetFileName()));
sender()->deleteLater();
}
public:
Window(QWidget * parent = 0) :
QWidget(parent),
m_thread(new QThread(this)),
m_index(new QSpinBox),
m_target(new QLineEdit),
m_log(new QPlainTextEdit)
{
QFormLayout * layout = new QFormLayout(this);
QPushButton * button = new QPushButton("Join Files");
button->setObjectName("pushButton");
layout->addRow("File Index", m_index);
layout->addRow("Append to File Name", m_target);
layout->addRow(button);
layout->addRow(m_log);
QMetaObject::connectSlotsByName(this);
m_thread->start();
m_log->appendPlainText(QString("Current directory: %1").arg(QDir::currentPath()));
}
~Window() {
m_thread->exit();
m_thread->wait();
}
};
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Window w;
w.show();
return a.exec();
}
#include "main.moc"
Каков точный вопрос, который вы столкнулись? – Hariprasad
'QString qString1 = str.toUtf8()' не имеет никакого смысла. Вы преобразовали 'str' в' QByteArray', содержащий представление UTF-8 строки, и сразу же перевели его обратно в QString, используя конструктор по умолчанию, который использует кодировку Latin1. Вместо этого вы должны использовать 'QByteArray byteArray = str.toLocal8Bit();', если вы хотите использовать эту строку в собственных функциях. И вы должны использовать 'QFile' вместо собственных функций. –
Это зависит от @PavelStrakhov: в Qt5 класс QString хранит 16-битный QChar, соответствующий Unicode 4.0 (http://qt-project.org/doc/qt-5.0/qtcore/qstring.html#details), а не Latin-1 который является стандартом Qt4.Тем не менее, использование toUtf8() и сохранение результата в QString прямо по-прежнему не имеет никакого смысла ... – Antwane