Russian Qt Forum

Qt => Общие вопросы => Тема начата: FluffyMan2000 от Октябрь 06, 2012, 20:58



Название: Отображение прогресса копирования файла
Отправлено: FluffyMan2000 от Октябрь 06, 2012, 20:58
Доброго времени суток. Стоит задача отображать прогресс копирования файла. QFile::copy() такой возможности не дает (или возможно все же из QFile::copy() узнать сколько в данный момент скопировано байт?), поэтому решил использовать такую конструкцию:

Код:
QFile sourceFile(source);
QFile destFile(destination);

sourceFile.open(QIODevice::ReadOnly);
destFile.open(QIODevice::WriteOnly);

qint64 size = sourceFile.size();

for (qint64 i = 0; i < size; i += 1024)
{
    destFile.write(sourceFile.read(i));
    sourceFile.seek(i);
    destFile.seek(i);

    qDebug() << (i * 100) / size << "%";
}

но есть две проблемы:
1) эта функция работает очень медленно
2) эта функция вылетает с ошибкой если:
- исходный файл весит меньше 1024 байт (не всегда вылетает)
- исходный файл весит больше 1024 байт, но в конце при копировании считывается порция 1024 байт из файла, но в нем реально осталось меньше, например. тогда он дописывается и вылетает программа с ошибкой.

Подскажите как решить эти проблемы.


Название: Re: Отображение прогресса копирования файла
Отправлено: V1KT0P от Октябрь 06, 2012, 21:05
О боже по 1 килобайту копировать, это просто жесть. Копируй хотя-бы по 10 метров( 10485760 байт ). Если следующий кусок меньше 10 метров, то копируй столько сколько есть.


Название: Re: Отображение прогресса копирования файла
Отправлено: FluffyMan2000 от Октябрь 06, 2012, 22:18
Как это алгоритмически сделать? берем остаток от деления размера файла на 10485760. Получили сколько раз копировать из исходного файла в файл назначения. А остаток - порция, которую дописать в конечный файл единоразово? Или как?


Название: Re: Отображение прогресса копирования файла
Отправлено: V1KT0P от Октябрь 06, 2012, 22:26
Как это алгоритмически сделать? берем остаток от деления размера файла на 10485760. Получили сколько раз копировать из исходного файла в файл назначения. А остаток - порция, которую дописать в конечный файл единоразово? Или как?
Да, но идеально будет если сделаешь два потока. Первый читает, второй пишет. Но первый должен следить и не особо спешить если второй не успевает записать. Для этого лучше организовать два буфера, тогда это будет выглядеть так:
Первый считывает кусок в первый буфер, сигнализирует второму потоку и считывает во второй буфер. Второй поток записывает из первого буфера. По окончании сигнализирует первому, который меняет указатели на буферы и оповещает второй поток и тут-же считывает во второй буфер и так пока не скопируется весь файл. И советую не привязываться к определенной длине блока, если второй поток простаивает, то стоит увеличить размер блока.


Название: Re: Отображение прогресса копирования файла
Отправлено: FluffyMan2000 от Октябрь 06, 2012, 23:00
Сложновато с потоками. У меня процесс копирования уже в отдельном потоке идёт и нужно всего лишь прогресс отображать. Завтра попробую и отпишусь.


Название: Re: Отображение прогресса копирования файла
Отправлено: Alex Custov от Октябрь 06, 2012, 23:05
Почему вы решили заняться Qt, когда не можете написать настолько простой алгоритм, который дают студентам первого курса для разминки?


Название: Re: Отображение прогресса копирования файла
Отправлено: FluffyMan2000 от Октябрь 06, 2012, 23:28
Очень помог Ваш комментарий при решении задачи


Название: Re: Отображение прогресса копирования файла
Отправлено: Alex Custov от Октябрь 06, 2012, 23:35
Очень помог Ваш комментарий при решении задачи

такие задачи нужно решать упорным трудом, раз за разом пытаясь ЛОГИЧЕСКИ понять и написать код, который будет работать. Никто вам в этом не поможет, либо вы сами себя сломаете, либо будете по любой мелочной причине бежать на форум. Ваша задача никакого отношения к Qt не имеет, это алгоритм на три строки для начинающих изучать Си и цикл while. Если вы хотите стать разработчиком - забудьте о форумах на полгода. Целиком и полностью.


Название: Re: Отображение прогресса копирования файла
Отправлено: FluffyMan2000 от Октябрь 07, 2012, 09:03
Отчасти с Вами согласен. Однако с qt это связано. При чтении документации на класс QIODevice и его метод ::read(qint64 maxSize) я выяснил, что он возвращает реально считанное количество байт. Поэтому в цикле while можно читать и писать порциями не беспокоясь, что считается или запишется лишние байты с порции. Попробую и скажу вышло или нет.

А про то, что только самостоятельное решение задач может помочь абсолютно согласен.


Название: Re: Отображение прогресса копирования файла
Отправлено: mutineer от Октябрь 07, 2012, 09:30
А зачем ты на каждой итерации делаешь seek ?


Название: Re: Отображение прогресса копирования файла
Отправлено: FluffyMan2000 от Октябрь 07, 2012, 09:45
А зачем ты на каждой итерации делаешь seek ?

перемещаю позицию курсора на новую порцию для считывания


Название: Re: Отображение прогресса копирования файла
Отправлено: mutineer от Октябрь 07, 2012, 10:03
А зачем ты на каждой итерации делаешь seek ?

перемещаю позицию курсора на новую порцию для считывания

Курсор сам смещается при каждом чтении/записи, а ты его на каждой итерации двигаешь назад и переписываешь одни и те же данные по несколько раз


Название: Re: Отображение прогресса копирования файла
Отправлено: FluffyMan2000 от Октябрь 07, 2012, 10:19
А зачем ты на каждой итерации делаешь seek ?

перемещаю позицию курсора на новую порцию для считывания

Курсор сам смещается при каждом чтении/записи, а ты его на каждой итерации двигаешь назад и переписываешь одни и те же данные по несколько раз

понял. Вот этот код работает:
Код:
   
dest.open(QIODevice::WriteOnly);
file.open(QIODevice::ReadOnly);

QByteArray buf = 0;
qint64 progres = 0;
while (!(buf = file.read(1048576)).isEmpty())
{
     dest.write(buf);
     progres += buf.size();
     qDebug() << (double)((progres * 100) / file.size()) << "%";
}

но программа выдает ошибку если ее закрыть. в чем проблема может быть (файлы закрываются) ?


Название: Re: Отображение прогресса копирования файла
Отправлено: mutineer от Октябрь 07, 2012, 10:22
А ошибка в этом мире только одна бывает, что ты так скромно умалчиваешь о ее типе?


Название: Re: Отображение прогресса копирования файла
Отправлено: FluffyMan2000 от Октябрь 07, 2012, 10:36
А ошибка в этом мире только одна бывает, что ты так скромно умалчиваешь о ее типе?

на консоль выдается сообщение
Код:
Программа неожиданно завершилась.
D:\Путь_к_файлу\FileOperator-build-desktop-Qt_4_7_4_for_Desktop_-_MinGW_4_4__Qt_SDK_______\release\FileOperator.exe завершился с кодом -1073741819

и выскакивает стандартное окно ОС http://rghost.ru/40788568.view (http://rghost.ru/40788568.view)


Название: Re: Отображение прогресса копирования файла
Отправлено: mutineer от Октябрь 07, 2012, 10:40
А если попробовать отладку?


Название: Re: Отображение прогресса копирования файла
Отправлено: FluffyMan2000 от Октябрь 07, 2012, 11:21
А если попробовать отладку?

ошибка не связана была с темой. спасибо за помощь всем.


Название: Re: Отображение прогресса копирования файла
Отправлено: Igors от Октябрь 07, 2012, 11:40
С "классиками" сами разберетесь, а цикл лучше сконструировать так

Код
C++ (Qt)
qint64 bytesTotal = srcFile.size();   // число байтов которое нужно прочитать/скопировать
qint64 bytesDone = 0;                 // число прочитанных
const qint64 bufSize = 1024 * 64;  // дело вкуса но больший  буфер не особо быстрее
 
while (bytesDone < bytesTotal) {
qint64 bytesRead = qMin(bytesTotal - bytesDone, bufSize);  // размер порции данных
bytesDone += bytesRead;  // обновляем число прочитанных
 
...  // копируемся (используем bytesRead)
 
}