2013-12-17 6 views
0

У меня есть эта программа, я хотел бы отправить данные из нескольких файлов в один файл с помощью цикла, но это, похоже, не работает должным образом.Qt Невозможно добавить несколько данных файла к одному

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

Каков точный вопрос, который вы столкнулись? – Hariprasad

+1

'QString qString1 = str.toUtf8()' не имеет никакого смысла. Вы преобразовали 'str' в' QByteArray', содержащий представление UTF-8 строки, и сразу же перевели его обратно в QString, используя конструктор по умолчанию, который использует кодировку Latin1. Вместо этого вы должны использовать 'QByteArray byteArray = str.toLocal8Bit();', если вы хотите использовать эту строку в собственных функциях. И вы должны использовать 'QFile' вместо собственных функций. –

+0

Это зависит от @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

ответ

1

Там же несколько проблем:

  1. У вас есть как C++ и Qt, используйте QFile, не используйте обнаженных файлы C!

  2. qString1 является бедной копией str, так что в этом смысл?

  3. Копирование файлов по символам выполняется довольно плохо.

  4. Вы не хотите блокировать свой графический интерфейс при выполнении файловых операций в целом. Они должны выполняться в отдельном потоке.

Ниже приведен пример того, как это можно сделать. Я стремился полностью использовать то, что 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, а другой, который только выполняет сериализованный доступ к файлам.

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" 
+0

Я бы не сказал, что 'fgetc' и' fputc' выполняют особенно плохо. Они выполняют внутреннюю буферизацию, и производительность может быть привязана к IO, только с увеличением загрузки процессора. – hyde

+1

@hyde: Конечно, но в этом случае они просто демонстрация того, кто не знает, как это сделать в противном случае. Они не используются по дизайну, они используются случаем. Я хочу, чтобы не укрепить этот способ. –