【问题标题】:CopyFile fails with error code 3 (ERROR_PATH_NOT_FOUND)CopyFile 失败并出现错误代码 3 (ERROR_PATH_NOT_FOUND)
【发布时间】:2016-04-01 18:44:10
【问题描述】:

所以,在开始之前,我一直在研究(不仅在 Stack Overflow),但我找不到解决问题的方法。

我正在尝试使用 Windows 的 CopyFile 函数将文件复制到某个位置(如果可能,在复制它的同时更改其名称)。

我创建了一个示例程序来显示错误。

#include <iostream>
#include <Windows.h>
using namespace std;

int main()
{
    cout << "Copy in progress" << endl;
    bool X = CopyFile(L"test.txt", L"C:\\", 1); //NOT C: nor C:\\ 
    if (!X){ cout << "FALLO AL COPIAR\n"; cout << "Error: "<<GetLastError();}
    else{ cout << "COPIADO CORRECTO";  }
    cin.get(); cin.get();
    return 0;
}

GetLastError() 返回 3 - 这意味着 ERROR_PATH_NOT_FOUND - 但是,相信我,我已经检查了每个文件(test.txt 与构建的 .exe 在同一个位置,我以管理员身份运行......)和它仍然给出 3。

我无法让它工作。请注意 L"test" 这样做是因为我使用具有某些字符集设置的 Visual Studio,我尝试更改该配置并使用 "test.txt" -> 仍然是错误 3。

【问题讨论】:

  • 您是否尝试过使用完整路径?
  • 永远不要发布代码截图。而是发布代码。屏幕截图会避开文本搜索,让您的问题不易被发现。
  • 我恢复了编辑。请让我们坚持原来的问题。如果您不明白 L 的含义以及使用它的原因,那么您还没有准备好在 Windows 上编写代码。
  • CopyFile 是一个经过测试、验证、信任和记录的 API。如果它说,错误 0x3,那肯定意味着,你以某种方式弄乱了文件的路径(在源或目标或两者中)。

标签: c++ windows winapi file-copying


【解决方案1】:

尝试:

CopyFile(L"test.txt", L"C:\\test.txt", 1);

【讨论】:

  • 好的,这对我有用。但是现在,在真正的程序中(因为那是一个例子,我都不能运行)我有一个包含源的 wchar_t 数组和另一个包含目标的数组。两者都有最后的文件名,但是(我相信是由单个 '\' 引起的)它给了我错误 3。我会尝试更好地解释我的情况。即使我有正确的变量(完整路径,不是相对的,提供的文件名),它也会给出错误 3(是否为管理员)。有什么想法吗?
  • 没有解释,问题是什么,已经采取了哪些措施来解决它,以及为什么,这个答案几乎没有帮助。
  • 好吧,我试着解释一下。我不确定问题是什么,以及我是如何解决的,但是对我的代码进行更改时,我推断出: 1. 在环境变量上使用 CopyFile() 时有一些限制。它不能复制到某些变量,例如 %userprofile% 但可以复制到 %temp% (不确定,因为我看不到复制的文件,即使我的工具说它已被复制..) 2. 使用 CopyFile( ) 在环境变量上,您有时需要替换路径中的文件名。就是这样。它还没有完全解决,但是如果我取得了一些成就,我会尝试发布更新。
  • 如果您不确定 OP 在问什么,请写评论。 comment everywhere privilege 将在您获得 50 声望后获得。作为更新发布的评论甚至与问题无关,也没有解决我上面指出的任何问题。这并不构成对问题的回答。
【解决方案2】:

您可以从MSDN:查看函数签名

BOOL WINAPI CopyFile(
  _In_ LPCTSTR lpExistingFileName,
  _In_ LPCTSTR lpNewFileName,
  _In_ BOOL    bFailIfExists
);

我想,它不需要目标目录(例如cp 命令),而是整个文件名。提示:确保在调用CopyFile时创建了最终文件名之前的所有目录。

还有一个提示:在 POSIX 系统上,您没有类似的例程(好吧,您在 OS X 上也有类似的东西,但它是特定于操作系统的)。但是,您可以执行以下操作(这就是 CopyFile 在幕后的实际工作方式):

  1. 通过open(对于 POSIX)或CreateFile(对于 Windows)打开两个文件句柄。打开一个句柄用于读取(源文件),另一个打开用于写入(目标文件)。
  2. 从您为读入临时缓冲区而打开的句柄中读取(BUFSIZ 缓冲区大小通常就足够了)。
  3. 将缓冲区中的数据写入为写入而打开的句柄。
  4. 重复直到有字节可用到可读句柄中。

这是它通常的工作方式,尽管特定于操作系统的例程可能会通过一些黑魔法进行调整(例如,它们可以执行内存映射、将文件从一个描述符发送到另一个描述符而不退出内核模式等)。

【讨论】:

  • CopyFile 有效。请不要提出其他建议@ghost
  • @David:请仔细阅读我的回答。它没有告诉 OP CopyFile 坏了;它解释了 如何 它的工作原理,同时演示了为什么 CopyFile 有这样的签名(我的意思是为什么它有两个文件名,而不是文件名和目录名)。
  • 还值得指出的是,CopyFile 所做的远比您说的要多。它也复制元数据和备用流。
  • 备用数据流是文件内容。请不要提出不符合要求的解决方案。
  • 阅读您的答案的第一条评论,看看提问者对信息的理解程度。我建议您删除答案的第二部分。
【解决方案3】:

您需要提供一个文件名:

bool X = CopyFile(L"test.txt", L"C:\\test.txt", 1);

【讨论】:

  • 并且您应该在第一个参数中使用完整路径,而不是相对路径。无法保证进程的初始工作目录与 .exe 所在的目录相同。最好检索调用进程的实际路径并将所需的文件名附加到它。
  • @RemyLebeau - 确实。
  • 伙计们,我已经“发现”了错误(或多或少)。在我的代码中,我使用 string path = getenv("USERPROFILE");它检索了我的 USERPROFILE 变量(或任何其他变量) 令人惊讶的是,如果使用 %TEMP% (“TEMP”),CopyFile (似乎)可以很好地复制文件,但不能使用任何其他既不是管理员也不是管理员的变量,所以,大声笑。跨度>
  • @PedroJavierFernández - pathsecondPathfinalPath 的内容是什么?
  • @PedroJavierFernández:你问了一个不同的问题,这个问题已经用这个答案回答了。如果您需要帮助从环境变量构造完全限定的路径名​​,请提出不同的问题。如果 CopyFile 失败并显示错误代码 3,则说明您弄乱了源或目标(或两者)路径名。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-09-04
  • 2012-01-22
  • 2021-08-12
  • 1970-01-01
  • 2014-01-25
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多