2014-04-06 81 views
0

時,我有以下代碼:CPP:錯誤使用重命名功能

void CommandRenHandler::HandleCommand(Socket* socket, std::vector<std::string>& rvParams){ 
    if (rvParams.size() < 2){ 
     socket->writeline("Not enough parameters specified"); 
     return; 
    } 

    std::string filePath = BASE_DIRECTORY; 
    filePath.append(rvParams.at(0)); 
    std::string filePath2 = BASE_DIRECTORY; 
    filePath2.append(rvParams.at(1)); 
    int result = rename(filePath.c_str(), filePath2.c_str()); 

    // TEST 
    std::cout << filePath << " " << filePath2 << std::endl << "result: " << result << std::endl; 

    if (result == 0) 
     socket->writeline("File renamed"); 
    else 
     socket->writeline("Could not rename file"); 
} 

在此功能中我收到了需要重命名的文件兩種文件路徑。我已經添加了TEST cout。

我有1個文件需要重命名。下面是我的測試輸入和輸出:

1(手動重命名文件 - 作品INTENTED):

在控制檯:

REN one\image.png one\new_image.png 

調試:

filePath = "C:\\...\\one\\image.png" 
filePath2 = "C:\\...\\one\\new_image.png" 
result = 0; 

測試輸出:

C:\...\one\image.png C:\...\one\new_image.png result: 0 

2(背手動重命名文件 - WORKS AS INTENTED):

在控制檯:

REN one\new_image.png one\image.png 

調試:

filePath = "C:\\...\\one\\new_image.png" 
filePath2 = "C:\\...\\one\\image.png" 
result = 0; 

測試輸出:

C:\...\one\new_image.png C:\...\one\image.png result: 0 

3 (使用SYNC,使用相同的重命名 - 不工作):

在控制檯:

SYNC one one 

(如果一個文件被改變或僅重命名此方法檢查。在這種情況下,它重命名,並會發送信息下方的重命名功能,就像一個普通REN如上)

調試:

filePath = "C:\\...\\one\\image.png" 
filePath2 = "C:\\...\\one\\new_image.png" 
result = -1; 

測試輸出:

C:\...\one\image.png C:\...\one\image.png result: -1 

1(重新命名同一文件,與第1步完全相同,但是這次我們也會再次出現錯誤 - 無法工作)

在控制檯中:

REN one\image.png one\new_image.png 

調試:

filePath = "C:\\...\\one\\image.png" 
filePath2 = "C:\\...\\one\\new_image.png" 
result = -1; 

測試輸出:

C:\...\one\image.png C:\...\one\new_image.png result: -1 

所以,我的問題是:爲什麼C的重命名功能++起初工作正常,但後來未能通過SYNC功能時之後我也無法手動使用REN功能。

TL; DR:有人可以看到問題所在的部分代碼提供嗎?或者有什麼方法可以查看導致重命名錯誤的原因?因爲剛剛-1是一種無用的調試結果。

在此先感謝。

PS: 這裏是SYNC代碼,以防萬一:

std::vector<std::string> vParams; 
// Check wether file is completely different or just renamed 
std::string oldFile = FileJustRenamed(file); 
if (oldFile != "") { 
    vParams.push_back(std::string("REN")); 
    vParams.push_back(oldFile); 
    vParams.push_back(file); 

    std::cout << "Renaming " << file << std::endl; 
    ren_handler->HandleCommand(socket, vParams); 
} 

PSS:是的,路徑不完全匹配。 filePaths中的「...」是出於隱私原因。

對於那些想知道的問題:C++在Windows中編碼,而不是Linux。

編輯:第一個rvParam(「REN」)將在創建CommandRenHandler的工廠類中被刪除。在那裏,HandleCommand函數將被第一個rvParam(在這種情況下爲「REN」)被移除。所以rvParams.at(0)是第一個filePath,而rvParams.at(1)是第二個filePath。

對不起,我以前沒有在我的代碼中提到過。

+2

在'rename'的'newname'部分再次嘗試沒有完整路徑。 MSDN文檔警告各種情況,但在這個特定點上有點不清楚。順便說一句,查找'errno' - 它提供了一個更清晰的錯誤描述'-1'。 – usr2564301

+0

您是否嘗試重命名爲已存在的文件?如果是這樣,你可能需要刪除現有的目標文件,然後再使用'rename' ... –

+0

@Jongware我嘗試了它沒有完整的路徑,但它仍然給出了相同的錯誤。我也添加了errno並返回nr。 13. –

回答

1

Nemanja Boric的提示後,該文件可能仍然在某處開放,我翻閱了我的代碼。事實證明,我仍然開放了一個ifstream(但這不是問題,因爲在關閉它之後仍然出現同樣的問題)。

然後我繼續看,注意到我沒有關閉另一個流在我的代碼中的其他地方,因爲提前返回聲明。

TL; DR:必須在我的代碼中關閉一個打開的流才能重命名文件。

1

好了,你有差一錯誤:

if (oldFile != "") { 
    vParams.push_back(std::string("REN")); 
    vParams.push_back(oldFile); 
    vParams.push_back(file); 

    std::cout << "Renaming " << file << std::endl; 
    ren_handler->HandleCommand(socket, vParams); 
} 

這裏,vParams.at(0)"REN"字符串,您使用的是rename其中:

std::string filePath = BASE_DIRECTORY; 
filePath.append(rvParams.at(0));   // THIS IS "REN" and not the actual filename. 
std::string filePath2 = BASE_DIRECTORY; 
filePath2.append(rvParams.at(1)); 
int result = rename(filePath.c_str(), filePath2.c_str()); 

因此,基於我看,我猜這是HandleCommand的正確實施:

void CommandRenHandler::HandleCommand(Socket* socket, std::vector<std::string>& rvParams){ 
    if (rvParams.size() < 3){ 
     socket->writeline("Not enough parameters specified"); 
     return; 
    } 


    if(rvParams.at(0) == "REN") 
    { 
     std::string filePath = BASE_DIRECTORY; 
     filePath.append(rvParams.at(1)); 
     std::string filePath2 = BASE_DIRECTORY; 
     filePath2.append(rvParams.at(2)); 
     int result = rename(filePath.c_str(), filePath2.c_str()); 

     // TEST 
     std::cout << filePath << " " << filePath2 << std::endl << "result: " << result << std::endl; 

     if (result == 0) 
      socket->writeline("File renamed"); 
     else 
      socket->writeline("Could not rename file"); 
    } 
} 
+0

儘管在我發佈的代碼中看不到,但第一個參數將在工廠級別中刪除。所以它是rvParams與REN,filePath和filePath2(然後它使CommandRenHandler在工廠中並刪除了REN)。對不起,我沒有在我的代碼中說清楚。 –