我有这个程序,我想使用循环将多个文件的数据发送到一个文件中,但这似乎不能正常工作。
void MainWindow::on_pushButton_clicked()
{
FILE *fp1,*fp2;
char ch;
QString str="test"+i+".txt";
QString qString1 =str.toUtf8();
QByteArray byteArray = qString1.toUtf8();
const char* fname1 = byteArray.constData();
if(QFile::exists("test0.txt"))
fp1=fopen(fname1,"r");
fp2=fopen("CheckoutReport.txt","a");
do
{
ch=fgetc(fp1);
fputc(ch,fp2);
}
while(ch!=EOF);
fcloseall();
}
答案 0 :(得分:1)
有几个问题:
你有C ++ 和 Qt,使用QFile
,不要使用裸C文件!
qString1
是穷人的str
副本,那有什么意义呢?
逐个字符地复制文件的效果相当差。
一般情况下,您不希望在执行文件操作时阻止GUI。它们应该在一个单独的线程中完成。
以下是如何完成的一个示例。我一直在努力充分利用Qt所提供的功能,同时保持QWidget为基础。这是一个独立的单文件示例,只需将其作为单独的文件添加到Qt Creator中的qt guy项目,然后构建并运行。请记住,此代码将打开其当前工作目录中的文件!
在代码复杂性方面使用另一个线程的成本实际上是6行。如果您不关心使用单独的文件访问线程,并且您的UI被网络上可能较慢的文件阻止等,那么可以删除以下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
发布到工作对象。此事件将由线程中运行的事件循环拾取,并将导致调用worker的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"