您可以使用較低級別的功能做類似的事情。這是我寫的與10.12之前的SDK一起使用的代碼。如果您針對10.12 SDK或更高版本進行編譯,則可以使其更簡單,如果您的部署目標爲10.12或更高版本,則更簡單。
#ifndef RENAME_SWAP
#define RENAME_SWAP 0x00000002
#endif
/*!
@function ExchangeFiles
@abstract Given full paths to two files on the same volume,
swap their contents.
@discussion This is often part of a safe-save strategy.
@param inOldFile Full path to a file.
@param inNewFile Full path to a file.
@result 0 if all went well, -1 otherwise.
*/
int ExchangeFiles(const char* inOldFile, const char* inNewFile)
{
int result = -1;
static dispatch_once_t sOnce = 0;
static renameFuncType sRenameFunc = NULL;
// Try to get a function pointer to renamex_np, which is available in OS 10.12 and later.
dispatch_once(&sOnce,
^{
sRenameFunc = (renameFuncType) dlsym(RTLD_DEFAULT, "renamex_np");
});
// renamex_np is only available on OS 10.12 and later, and does not work on HFS+ volumes
// but does work on APFS volumes. Being the latest and greatest, we try it first.
if (sRenameFunc != NULL)
{
result = (*sRenameFunc)(inOldFile, inNewFile, RENAME_SWAP);
}
if (result != 0)
{
// exchangedata is an older function that works on HFS+ but not APFS.
result = exchangedata(inOldFile, inNewFile, 0);
}
if (result != 0)
{
// Neither function worked, we must go old school.
std::string nameTemplate(inOldFile);
nameTemplate += "-swapXXXX";
// Make a mutable copy of the template
std::vector<char> workPath(nameTemplate.size() + 1);
memcpy(&workPath[0], nameTemplate.c_str(), nameTemplate.size() + 1);
mktemp(&workPath[0]);
std::string tempPath(&workPath[0]);
// Make the old file have a temporary name
result = rename(inOldFile, tempPath.c_str());
// Put the new file data under the old name.
if (result == 0)
{
result = rename(inNewFile, inOldFile);
}
// Put the old data under the new name.
if (result == 0)
{
result = rename(tempPath.c_str(), inNewFile);
}
}
return result;
}
只是要清楚 - 雖然這是首選的方法,但它實際上並沒有將replaceItemAtURL與withItemAtURL「交換」。完成此操作後,原始文件將位於同一目錄下的backupItemName中,然後需要與withItemAtURL交換以實現與FSExchangeObjectsCompat()相同的功能,對吧? – SMGreenfield
提供'backupItemName'是可選的。如果您沒有通過該選項或選項,那麼實施可能(並可能)執行您正在尋找的交易類型。 –
爲了將來的參考 - withItemAtURL上的「new」文件在替換replaceItemAtURL處的文件後始終爲DELETED。 replaceItemAtURL中的「原始」文件將被複制到backupItemName(如果提供),並且也將被刪除,除非指定了NSFileManagerItemReplacementWithoutDeletingBackupItem選項標誌。所以這與交易所不完全相同,但似乎足夠接近。不確定這是優於還是偏好在10.12或更高版本上使用renamex_np或APFS存在時。 – SMGreenfield