Я хочу скопировать каталог с одного диска на другой диск. Мой выбранный каталог содержит много подкаталогов и файлов.Копировать каталог с помощью Qt
Как я могу реализовать то же самое с помощью Qt?
Я хочу скопировать каталог с одного диска на другой диск. Мой выбранный каталог содержит много подкаталогов и файлов.Копировать каталог с помощью Qt
Как я могу реализовать то же самое с помощью Qt?
Жесткий путь. Скопируйте каждый файл отдельно.
QDir::entryList()
перебрать содержимое каталогаQDir::cd()
и QDir::cdUp()
, чтобы входить и выходить из каталоговQDir::mkdir()
и QDir::mkpath()
для создания нового дерева каталоговQFile::copy()
для копирования фактических файловВручную можно сделать следующее:
1). с func ниже вы создаете список папок/файлов (рекурсивно) - файлы назначения.
static void recurseAddDir(QDir d, QStringList & list) {
QStringList qsl = d.entryList(QDir::NoDotAndDotDot | QDir::Dirs | QDir::Files);
foreach (QString file, qsl) {
QFileInfo finfo(QString("%1/%2").arg(d.path()).arg(file));
if (finfo.isSymLink())
return;
if (finfo.isDir()) {
QString dirname = finfo.fileName();
QDir sd(finfo.filePath());
recurseAddDir(sd, list);
} else
list << QDir::toNativeSeparators(finfo.filePath());
}
}
2). то вы можете начать копирование файлов из списка назначения в новый каталог источника, как, что:
for (int i = 0; i < gtdStringList.count(); i++) {
progressDialog.setValue(i);
progressDialog.setLabelText(tr("%1 Coping file number %2 of %3 ")
.arg((conf->isConsole) ? tr("Making copy of the Alta-GTD\n") : "")
.arg(i + 1)
.arg(gtdStringList.count()));
qApp->processEvents(QEventLoop::ExcludeUserInputEvents);
if (progressDialog.wasCanceled()) {
// removing tmp files/folders
rmDirectoryRecursive(tmpFolder);
rmDirectoryRecursive(tmpFolderPlus);
setEnableGUI(true);
return;
}
// coping
if (!QFile::copy(gtdStringList.at(i), tmpStringList.at(i))) {
if (warningFlag) {
QMessageBox box(this);
QString name = tr("Question");
QString file1 = getShortName(gtdStringList.at(i), QString("\\...\\"));
QString file2 = getShortName(tmpStringList.at(i), QString("\\...\\"));
QString text = tr("Cannot copy <b>%1</b> <p>to <b>%2</b>" \
"<p>This file will be ignored, just press <b>Yes</b> button" \
"<p>Press <b>YesToAll</b> button to ignore other warnings automatically..." \
"<p>Or press <b>Abort</b> to cancel operation").arg(file1).arg(file2);
box.setModal(true);
box.setWindowTitle(name);
box.setText(QString::fromLatin1("%1").arg(text));
box.setIcon(QMessageBox::Question);
box.setStandardButtons(QMessageBox::YesToAll | QMessageBox::Yes | QMessageBox::Abort);
switch (box.exec()) {
case (QMessageBox::YesToAll):
warningFlag = false;
break;
case (QMessageBox::Yes):
break;
case (QMessageBox::Abort):
rmDirectoryRecursive(tmpFolder);
rmDirectoryRecursive(tmpFolderPlus);
setEnableGUI(true);
return;
}
}
}
}
И это все. Удачи!
Я хотел что-то подобное, и прибегая к помощи (напрасно), так это то, где я должен:
static bool cpDir(const QString &srcPath, const QString &dstPath)
{
rmDir(dstPath);
QDir parentDstDir(QFileInfo(dstPath).path());
if (!parentDstDir.mkdir(QFileInfo(dstPath).fileName()))
return false;
QDir srcDir(srcPath);
foreach(const QFileInfo &info, srcDir.entryInfoList(QDir::Dirs | QDir::Files | QDir::NoDotAndDotDot)) {
QString srcItemPath = srcPath + "/" + info.fileName();
QString dstItemPath = dstPath + "/" + info.fileName();
if (info.isDir()) {
if (!cpDir(srcItemPath, dstItemPath)) {
return false;
}
} else if (info.isFile()) {
if (!QFile::copy(srcItemPath, dstItemPath)) {
return false;
}
} else {
qDebug() << "Unhandled item" << info.filePath() << "in cpDir";
}
}
return true;
}
Он использует rmDir
функцию, которая выглядит очень похоже:
static bool rmDir(const QString &dirPath)
{
QDir dir(dirPath);
if (!dir.exists())
return true;
foreach(const QFileInfo &info, dir.entryInfoList(QDir::Dirs | QDir::Files | QDir::NoDotAndDotDot)) {
if (info.isDir()) {
if (!rmDir(info.filePath()))
return false;
} else {
if (!dir.remove(info.fileName()))
return false;
}
}
QDir parentDir(QFileInfo(dirPath).path());
return parentDir.rmdir(QFileInfo(dirPath).fileName());
}
Это не обрабатывает ссылки и специальные файлы, кстати.
void copyPath(QString src, QString dst)
{
QDir dir(src);
if (! dir.exists())
return;
foreach (QString d, dir.entryList(QDir::Dirs | QDir::NoDotAndDotDot)) {
QString dst_path = dst + QDir::separator() + d;
dir.mkpath(dst_path);
copyPath(src+ QDir::separator() + d, dst_path);
}
foreach (QString f, dir.entryList(QDir::Files)) {
QFile::copy(src + QDir::separator() + f, dst + QDir::separator() + f);
}
}
Я не знаю, если это моя установка, или этот код в Qt 5.6, но этот код, кажется, висит. Это делает копирование каталогов, но никогда не заканчивается. Weird. –
Хм, да. Работа первой копии работает, а затем последующие копии идут бананы. Создайте каталог, затем скопируйте этот каталог в поддиректор. Первые работы, во-вторых, удары, мертвые. –
Это в основном petch's answer с небольшим изменением в связи с этим нарушения для меня в Qt 5.6 (это верхний вопрос хит), так что все идет в кредит petch.
функция
bool copyPath(QString sourceDir, QString destinationDir, bool overWriteDirectory)
{
QDir originDirectory(sourceDir);
if (! originDirectory.exists())
{
return false;
}
QDir destinationDirectory(destinationDir);
if(destinationDirectory.exists() && !overWriteDirectory)
{
return false;
}
else if(destinationDirectory.exists() && overWriteDirectory)
{
destinationDirectory.removeRecursively();
}
originDirectory.mkpath(destinationDir);
foreach (QString directoryName, originDirectory.entryList(QDir::Dirs | \
QDir::NoDotAndDotDot))
{
QString destinationPath = destinationDir + "/" + directoryName;
originDirectory.mkpath(destinationPath);
copyPath(sourceDir + "/" + directoryName, destinationPath, overWriteDirectory);
}
foreach (QString fileName, originDirectory.entryList(QDir::Files))
{
QFile::copy(sourceDir + "/" + fileName, destinationDir + "/" + fileName);
}
/*! Possible race-condition mitigation? */
QDir finalDestination(destinationDir);
finalDestination.refresh();
if(finalDestination.exists())
{
return true;
}
return false;
}
Использование:
/*! Overwrite existing directories. */
bool directoryCopied = copyPath(sourceDirectory, destinationDirectory, true);
/*! Do not overwrite existing directories. */
bool directoryCopied = copyPath(sourceDirectory, destinationDirectory, false);
Что поделаешь и почему? –
Попробуйте это:
bool copyDirectoryFiles(const QString &fromDir, const QString &toDir, bool coverFileIfExist)
{
QDir sourceDir(fromDir);
QDir targetDir(toDir);
if(!targetDir.exists()){ /* if directory don't exists, build it */
if(!targetDir.mkdir(targetDir.absolutePath()))
return false;
}
QFileInfoList fileInfoList = sourceDir.entryInfoList();
foreach(QFileInfo fileInfo, fileInfoList){
if(fileInfo.fileName() == "." || fileInfo.fileName() == "..")
continue;
if(fileInfo.isDir()){ /* if it is directory, copy recursively*/
if(!copyDirectoryFiles(fileInfo.filePath(),
targetDir.filePath(fileInfo.fileName()),
coverFileIfExist))
return false;
}
else{ /* if coverFileIfExist == true, remove old file first */
if(coverFileIfExist && targetDir.exists(fileInfo.fileName())){
targetDir.remove(fileInfo.fileName());
}
// files copy
if(!QFile::copy(fileInfo.filePath(),
targetDir.filePath(fileInfo.fileName()))){
return false;
}
}
}
return true;
}
Благодарим вас за этот фрагмент кода, который может оказать немедленную помощь. Правильное объяснение [значительно улучшило бы] (// meta.stackexchange.com/q/114762) его образовательное значение, показав * почему * это хорошее решение проблемы и сделало бы его более полезным для будущих читателей с похожими, но не идентичные вопросы. Пожалуйста, отредактируйте свой ответ, чтобы добавить объяснение, и укажите, какие ограничения и допущения применяются. –
Я сделал библиотеку для работы с файлами с помощью команды в стиле оболочки API. Он поддерживает рекурсивную копию файлов и обрабатывает еще несколько условий.
https://github.com/benlau/qtshell#cp
Пример
cp("-a", ":/*", "/target"); // copy all files from qrc resource to target path recursively
cp("tmp.txt", "/tmp");
cp("*.txt", "/tmp");
cp("/tmp/123.txt", "456.txt");
cp("-va","src/*", "/tmp");
cp("-a", ":resource","/target");
я попытался разместить свою коррекцию как редактировать, но никто, кажется, понимают это, поэтому я выложу его здесь. используя «QString («% 1 /% 2 »). arg (d.path()). arg (file)' обычно не очень хорошая идея, поскольку «% 1» или «% 2» можно найти (в большинстве файловых систем) в имени файла или пути. возьмите этот путь, созданный cygwin в качестве примера 'c: \ cyg \ ftp% 3a% 2f% 2fcygwin.mirrorcatalogs.com% 2fcygwin% 2f'. – vikki
позволяет сказать, что это то, что хранится в 'd.path()' и 'file' имеет' text.txt'. '% 1' будет заменен на 'd.path()', чтобы сформировать 'c: \ cyg \ ftp% 3a% 2f% 2fcygwin.mirrorcatalogs.com% 2fcygwin% 2f /% 2'. наконец, вы получите 'c: \ cyg \ ftp% 3atext.txtftext.txtfcygwin.mirrorcatalogs.comtext.txtfcygwintext.txtf/text.txt'. лучшим вариантом является 'd.path(). append ('/'). append (file)' – vikki
@vikki: Да! Ты прав! – mosg