Qt无法将多个文件数据附加到一个

时间:2013-12-17 09:00:45

标签: qt file-copying

我有这个程序,我想使用循环将多个文件的数据发送到一个文件中,但这似乎不能正常工作。

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();
}

1 个答案:

答案 0 :(得分:1)

有几个问题:

  1. 你有C ++ Qt,使用QFile,不要使用裸C文件!

  2. qString1是穷人的str副本,那有什么意义呢?

  3. 逐个字符地复制文件的效果相当差。

  4. 一般情况下,您不希望在执行文件操作时阻止GUI。它们应该在一个单独的线程中完成。

  5. 以下是如何完成的一个示例。我一直在努力充分利用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,另一个只执行序列化文件访问。

    screenshot

    #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"