有幾個問題:
你有兩個C++ 和 Qt中,用QFile
,不要使用明火的C文件!
qString1
是窮人的str
副本,所以有什麼意義呢?
逐個字符地複製文件表現相當差。
一般來說,您不想在執行文件操作時阻止您的GUI。他們應該在一個單獨的線程中完成。
下面是它如何完成的一個例子。我努力充分利用Qt提供的功能,同時保持QWidget爲基礎。這是一個自包含的單文件示例,只需將其作爲單獨文件添加到Qt Creator中的qt項目項目中,然後構建並運行即可。請記住,此代碼將在其當前工作目錄中打開文件!
根據代碼複雜度使用另一個線程的成本實際上是6行。如果您不關心使用單獨的文件訪問線程,並且您的用戶界面被網絡上可能較慢的文件阻塞等情況良好,則可以刪除以下6行,而無需對代碼進行任何其他更改。這就是Qt的美麗。
QThread * m_thread;
w->moveToThread(m_thread);
m_thread(new QThread(this)),
m_thread->start();
m_thread->exit();
m_thread->wait();
不到位線程,你也可以用一個簡單的w->joinFiles()
更換QMetaObject::invokeMethod(w, "joinFiles");
。使用invokeMethod
而不是直接調用的原因是調用對象正在運行的線程中的插槽。 invokeMethod
將在幕後向工作者對象發佈QMetaCallEvent
。該事件將被線程中運行的事件循環拾取,並且將導致調用工作人員的joinFiles
插槽,該插槽在正確線程 - worker->thread()
內執行。
請注意,我不是從QThread
派生的,並且只有一個線程用於所有文件操作。如果您的出發點是在GUI線程中完成所有文件訪問,那麼這非常合適。這樣就有兩個線程:一個只做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表示形式,並使用使用Latin1編碼的默認構造函數立即將其轉換回QString。你應該使用'QByteArray byteArray = str.toLocal8Bit();'而不是如果你想在本地函數中使用這個字符串。你應該使用'QFile'而不是原生函數。 –
這取決於@PavelStrakhov:在Qt5中,QString類存儲對應於Unicode 4.0(http://qt-project.org/doc/qt-5.0/qtcore/qstring.html#details)的16位QChar,而非Latin-1這是Qt4的默認設置。也就是說,使用toUtf8()並直接將結果存儲在QString中仍然沒有任何意義... – Antwane