как выполнить boost::filesystem copy_file с перезаписью

Функция Windows API CopyFile имеет аргумент BOOL bFailIfExists, который позволяет вам контролировать, хотите ли вы перезаписать целевой файл, если он существует.

Функция boost::filesystem copy_file не имеет такого аргумента и завершится ошибкой, если целевой файл существует. Есть ли элегантный способ использовать функцию boost copy_file и перезаписать целевой файл? Или лучше просто использовать Windows API? Моя текущая целевая платформа — Windows, но я предпочитаю использовать STL и, где это возможно, повышать производительность, чтобы не зависеть от платформы моего кода.

Спасибо.


person Dani van der Meer    schedule 06.05.2009    source источник


Ответы (4)


Есть третий аргумент enum для copy_file, boost::filesystem::copy_option::overwrite_if_exists.

copy_file(source_path, destination_path, copy_option::overwrite_if_exists);

https://www.boost.org/doc/libs/1_75_0/libs/filesystem/doc/reference.html

person anno    schedule 26.04.2010
comment
Спасибо анно. Я не знал об этом. Кажется, эта опция была добавлена ​​где-то между версией 1.35, которую я использовал, когда задавал вопрос, и версией 1.41, которую я использую сейчас. Я не могу найти изменение в истории изменений библиотеки. Но в любом случае, проблема решена. Я не уверен, должен ли я теперь принять ваш ответ, может быть, я спрошу на мете. - person Dani van der Meer; 27.04.2010
comment
Осторожно: кажется, что есть проблема с этим третьим аргументом в реализации POSIX. Смотрите ответ Виталия. - person Dani van der Meer; 05.12.2010
comment
@DanivanderMeer для посетителей этой страницы, эта ошибка была исправлена ​​много лет назад. - person Drew Dormann; 12.10.2014

Остерегайтесь boost::copy_file с copy_option::overwrite_if_exists! Если целевой файл существует и он меньше исходного, функция перезапишет только первый размер (from_file) байтов в целевом файле.

По крайней мере, для меня это было предостережением, так как я предположил, что copy_option::overwrite_if_exists влияет на файлы, а не на контент

person Vitaly P    schedule 16.11.2010
comment
Я пытался воспроизвести на своей платформе (Windows), но не смог. перезапись влияет на весь файл, независимо от его размера. На какой платформе вы тестировали? - person Dani van der Meer; 18.11.2010
comment
IFAIK copy_option::overwrite_if_exists существует только в *nix (по крайней мере, в boost-1.44 для файловой системы v2). Но это легко увидеть в исходном коде, файл открывается на запись с O_WRONLY, но без установленного флага O_TRUNC. - person Vitaly P; 19.11.2010
comment
Я использую буст 1.41. copy_option::overwrite_if_exists существует и для Windows. copy_file вызывает Win32 API CopyFile (версия A или W) с bFailIfExists в соответствии с параметром, который вы передаете в boost::copy_file. Так что, возможно, поведение для Windows и POSIX отличается? - person Dani van der Meer; 19.11.2010
comment
Да, это другое. Я только что представил ошибку для повышения. См. ПРОБЛЕМУ № 4930 (svn.boost.org/trac/boost/ticket/4930) - person Vitaly P; 04.12.2010
comment
Согласно boost, эта проблема была исправлена ​​в версии rev. 67067 (поэтому я ожидаю, что он будет включен в грядущий буст-1.46) - person Vitaly P; 08.12.2010

Сначала проверьте, существует ли целевой файл, и если да, то удалите его:

if (exists (to_fp))
    remove (to_fp);
copy_file (from_fp, to_fp);

Или, если вы беспокоитесь о том, что файл появится между тестом и копией, вы можете записать во временный файл, а затем переименовать его в файл назначения.

person jon-hanson    schedule 06.05.2009
comment
Да, это возможно. Но что, если операция копирования не удалась? Вы уже удалили цель. Он не имеет той же семантики, подобной транзакциям, что и CopyFile. - person Dani van der Meer; 06.05.2009
comment
Альтернатива переименования не дает вам этого? В любом случае, глядя на источник повышения, API не позволяет вам перезаписывать файл. Вы можете предложить это им в качестве улучшения. Тем временем вы можете взять свою собственную копию функции boost copy_file и изменить ее, чтобы она принимала дополнительный перезаписываемый параметр bool. - person jon-hanson; 06.05.2009
comment
Что ж, я думаю, логика переименования будет работать, но я надеялся, что в библиотеке есть что-то, что решает эту проблему, и что мне не придется решать это самому :). Я постараюсь предложить это как улучшение. Я думаю, что это логичная и полезная функция. В любом случае, спасибо за вашу помощь. Я, вероятно, сейчас буду использовать CopyFile. - person Dani van der Meer; 06.05.2009
comment
Дэни, целью использования boost является написание переносимого кода, почему из-за лени вы ставите под угрозу основную причину использования boost? - person Gaetano Mendola; 12.05.2009
comment
Мобильность, безусловно, важная причина использования Boost, но не обязательно главная. Я бы сказал, что основная причина использования такой библиотеки, как boost, а также Windows API, заключается в том, что вам не нужно самостоятельно реализовывать базовые функции (и тестировать, отлаживать и т. д.). В данном случае эти две причины противоречат друг другу, и я должен найти правильный компромисс. Что такое правильный компромисс, конечно, вопрос мнения :). - person Dani van der Meer; 13.05.2009
comment
Я решил принять этот ответ, хотя это не полный ответ на вопрос. По-видимому, лучшего ответа нет, и этот ответ описывает лучший подход. - person Dani van der Meer; 24.08.2009
comment
Возможно, вы захотите поднять его с помощью Boost. Очевидно, что Windows поддерживает это, а Unix использует флаги O_CREAT и O_EXCL для open(), поэтому я не понимаю, почему boost не может его поддерживать. - person jon-hanson; 25.08.2009

Есть ли элегантный способ использовать функцию boost copy_file и перезаписать целевой файл?

По-видимому, прямого API для этого нет.

Или лучше просто использовать Windows API? Моя текущая целевая платформа — Windows, но я предпочитаю использовать STL и, где это возможно, повышать производительность, чтобы не зависеть от платформы моего кода.

Из документации:

Предложение N1975 о включении Boost.Filesystem в Технический отчет 2 было принято Комитетом по стандартам C++. Библиотека Boost.Filesystem останется в соответствии с предложением файловой системы TR2, поскольку она проходит через процесс TR2. Обратите внимание, однако, что пространства имен и степень детализации заголовков различаются между Boost.Filesystem и предложением TR2.

Это убедительно свидетельствует о том, что придерживаться boost::filesystem — хорошая идея.

person dirkgently    schedule 06.05.2009