UpFileCopyExW 在现有文件上报告 ERROR_FILE_NOT_FOUND 为 0
UpFileCopyExW reports 0 with ERROR_FILE_NOT_FOUND on an existing file
上下文:
我有一个应用程序可以使用 QDirIterator
、过滤器和复制特定文件来搜索目录中的文件。
问题:
使用有效的 QDirIterator::next(), I ensure the file exists (as a unnecessary safe measure) using QFile::exists(QString) 结果。
GetLastError() reports ERROR_FILE_NOT_FOUND 错误:
ERROR_FILE_NOT_FOUND
2 (0x2)
The system cannot find the file specified.
核心代码:(详见底部)
// QString src (src file location), dst (destination file location)
QFileInfo fi(m_src);
QString dir = fi.dir().path();
const wchar_t* dirC = toLPCWSTR(dir);
QString src = QString(m_src).replace("/", "\");
QString dst = QString(m_src).replace("/", "\");
const wchar_t* localC_src = toLPCWSTR(src);
const wchar_t* localC_dst = toLPCWSTR(dst);
auto rc = CopyFileExW(localC_src, localC_dst, &BackupManager::copyProgress, this, &bStopBackup, 0);
if (rc == 0) {
DWORD lastError = GetLastError(); // Error = 0x32
bool dirExist = DirExists(dirC); // true
bool fileExists = FileExists(localC_src); // true
printWarning(TAG, QString("File Copy Error: %1").arg(getLastErrorMsg()));
#ifdef QT_DEBUG
if (FileExists(localC_src)) {
qDebug() << "#FailedCopy: Windows file exists but copy failed" << src; // this gets hit using the implemented c-style cast
}
else {
if (QFile::exists(src)) {
// =================================================
// < ------------------------------------- This is gets triggered
// =================================================
qDebug() << "#FailedCopy: Windows is really being full of shit! " << src; // this always gets triggered when using QString::toStdWString.c_str()
}
else {
qDebug() << "#FailedCopy: Windows file copy failed outright" << src;
}
}
// ...
} else {
// success
}
问题:
对我来说没有意义的是为什么QFile::exists(String)
报告FileCopyExW
找到的文件说系统找不到指定的文件。我错过了什么?
调试器图片:
完整代码实现:
static QString toString(HRESULT hr)
{
_com_error err{hr};
const TCHAR* lastError = err.ErrorMessage();
return QStringLiteral("Error 0x%1: %2").arg((quint32)hr, 8, 16, QLatin1Char('0'))
.arg(lastError);
}
static QString getLastErrorMsg()
{
DWORD lastError = GetLastError();
QString s = toString(HRESULT_FROM_WIN32(lastError));
return s;
}
BOOL FileExists(LPCWSTR szPath)
{
DWORD dwAttrib = GetFileAttributes(szPath);
return (dwAttrib != INVALID_FILE_ATTRIBUTES &&
!(dwAttrib & FILE_ATTRIBUTE_DIRECTORY));
}
// not used
static const wchar_t* toLPCWSTR(QString s)
{
std::wstring dstWString = s.toStdWString();
const wchar_t* localC_src = dstWString.c_str();
return localC_src;
}
static bool DirExists(LPCWSTR szPath)
{
DWORD ftyp = GetFileAttributes(szPath);
if (ftyp == INVALID_FILE_ATTRIBUTES)
return false; //something is wrong with your path!
if (ftyp & FILE_ATTRIBUTE_DIRECTORY)
return true; // this is a directory!
return false; // this is not a directory!
}
BackupResult BackupManager::copyFile(QString m_src, QString m_dst)
{
QFileInfo fi(m_src);
QString dir = fi.dir().path();
const wchar_t* dirC = toLPCWSTR(dir);
QString src = QString(m_src).replace("/", "\");
QString dst = QString(m_src).replace("/", "\");
const wchar_t* localC_src = toLPCWSTR(src);
const wchar_t* localC_dst = toLPCWSTR(dst);
// c-style casts
// LPCWSTR localC_src = (LPCWSTR) src.utf16();
// LPCWSTR localC_dst = (LPCWSTR) dst.utf16();
// LPCWSTR dirC = (LPCWSTR) dir.utf16();
auto rc = CopyFileExW(localC_src, localC_dst, &BackupManager::copyProgress, this, &bStopBackup, 0);
if (rc == 0) {
DWORD lastError = GetLastError(); // Error = 0x2 (2)
bool dirExist = DirExists(dirC); // false
bool fileExists = FileExists(localC_src); // false
printWarning(TAG, QString("File Copy Error: %1").arg(getLastErrorMsg()));
#ifdef QT_DEBUG
if (FileExists(localC_src)) {
qDebug() << "#FailedCopy: Windows file exists but copy failed" << src; // this gets hit using the implemented c-style cast
}
else {
if (QFile::exists(src)) {
qDebug() << "#FailedCopy: Windows is really being full of shit! " << src; // this always gets triggered when using QString::toStdWString.c_str()
}
else {
qDebug() << "#FailedCopy: Windows file copy failed outright" << src;
}
}
#endif
// copy failed
return BackupResult::IOError;
}
// copy success
return BackupResult::Success;
}
更新:
正如@john 的评论中提到的,我在指向源文件的目标文件方面遇到了问题,这显然不能正常工作。
解决了这个问题后,这突出显示了另一个错误 ERROR_INVALID_NAME:
ERROR_INVALID_NAME
123 (0x7B)
The filename, directory name, or volume label syntax is incorrect.
我通过发布的解决方案解决了这个问题。
这个函数有问题:
// not used
static const wchar_t* toLPCWSTR(QString s)
{
std::wstring dstWString = s.toStdWString();
const wchar_t* localC_src = dstWString.c_str();
return localC_src;
}
您正在返回一个已被解构的字符串的原始指针。
因此,这两行:
const wchar_t* localC_src = toLPCWSTR(src);
const wchar_t* localC_dst = toLPCWSTR(dst);
是未定义的行为,但最可能的结果是 localC_src
和 localC_dst
指向释放的内存。
最好保留你用 around 转换的 std::wstring
,同时仍然引用里面的指针
std::wstring strSrc = src.toStdWString();
std::wstring strDst = dst.toStdWString();
const wchar_t* localC_src = strSrc.c_str();
const wchar_t* localC_dst = strDst.c_str();
上下文:
我有一个应用程序可以使用 QDirIterator
、过滤器和复制特定文件来搜索目录中的文件。
问题:
使用有效的 QDirIterator::next(), I ensure the file exists (as a unnecessary safe measure) using QFile::exists(QString) 结果。
GetLastError() reports ERROR_FILE_NOT_FOUND 错误:
ERROR_FILE_NOT_FOUND
2 (0x2)
The system cannot find the file specified.
核心代码:(详见底部)
// QString src (src file location), dst (destination file location)
QFileInfo fi(m_src);
QString dir = fi.dir().path();
const wchar_t* dirC = toLPCWSTR(dir);
QString src = QString(m_src).replace("/", "\");
QString dst = QString(m_src).replace("/", "\");
const wchar_t* localC_src = toLPCWSTR(src);
const wchar_t* localC_dst = toLPCWSTR(dst);
auto rc = CopyFileExW(localC_src, localC_dst, &BackupManager::copyProgress, this, &bStopBackup, 0);
if (rc == 0) {
DWORD lastError = GetLastError(); // Error = 0x32
bool dirExist = DirExists(dirC); // true
bool fileExists = FileExists(localC_src); // true
printWarning(TAG, QString("File Copy Error: %1").arg(getLastErrorMsg()));
#ifdef QT_DEBUG
if (FileExists(localC_src)) {
qDebug() << "#FailedCopy: Windows file exists but copy failed" << src; // this gets hit using the implemented c-style cast
}
else {
if (QFile::exists(src)) {
// =================================================
// < ------------------------------------- This is gets triggered
// =================================================
qDebug() << "#FailedCopy: Windows is really being full of shit! " << src; // this always gets triggered when using QString::toStdWString.c_str()
}
else {
qDebug() << "#FailedCopy: Windows file copy failed outright" << src;
}
}
// ...
} else {
// success
}
问题:
对我来说没有意义的是为什么QFile::exists(String)
报告FileCopyExW
找到的文件说系统找不到指定的文件。我错过了什么?
调试器图片:
完整代码实现:
static QString toString(HRESULT hr)
{
_com_error err{hr};
const TCHAR* lastError = err.ErrorMessage();
return QStringLiteral("Error 0x%1: %2").arg((quint32)hr, 8, 16, QLatin1Char('0'))
.arg(lastError);
}
static QString getLastErrorMsg()
{
DWORD lastError = GetLastError();
QString s = toString(HRESULT_FROM_WIN32(lastError));
return s;
}
BOOL FileExists(LPCWSTR szPath)
{
DWORD dwAttrib = GetFileAttributes(szPath);
return (dwAttrib != INVALID_FILE_ATTRIBUTES &&
!(dwAttrib & FILE_ATTRIBUTE_DIRECTORY));
}
// not used
static const wchar_t* toLPCWSTR(QString s)
{
std::wstring dstWString = s.toStdWString();
const wchar_t* localC_src = dstWString.c_str();
return localC_src;
}
static bool DirExists(LPCWSTR szPath)
{
DWORD ftyp = GetFileAttributes(szPath);
if (ftyp == INVALID_FILE_ATTRIBUTES)
return false; //something is wrong with your path!
if (ftyp & FILE_ATTRIBUTE_DIRECTORY)
return true; // this is a directory!
return false; // this is not a directory!
}
BackupResult BackupManager::copyFile(QString m_src, QString m_dst)
{
QFileInfo fi(m_src);
QString dir = fi.dir().path();
const wchar_t* dirC = toLPCWSTR(dir);
QString src = QString(m_src).replace("/", "\");
QString dst = QString(m_src).replace("/", "\");
const wchar_t* localC_src = toLPCWSTR(src);
const wchar_t* localC_dst = toLPCWSTR(dst);
// c-style casts
// LPCWSTR localC_src = (LPCWSTR) src.utf16();
// LPCWSTR localC_dst = (LPCWSTR) dst.utf16();
// LPCWSTR dirC = (LPCWSTR) dir.utf16();
auto rc = CopyFileExW(localC_src, localC_dst, &BackupManager::copyProgress, this, &bStopBackup, 0);
if (rc == 0) {
DWORD lastError = GetLastError(); // Error = 0x2 (2)
bool dirExist = DirExists(dirC); // false
bool fileExists = FileExists(localC_src); // false
printWarning(TAG, QString("File Copy Error: %1").arg(getLastErrorMsg()));
#ifdef QT_DEBUG
if (FileExists(localC_src)) {
qDebug() << "#FailedCopy: Windows file exists but copy failed" << src; // this gets hit using the implemented c-style cast
}
else {
if (QFile::exists(src)) {
qDebug() << "#FailedCopy: Windows is really being full of shit! " << src; // this always gets triggered when using QString::toStdWString.c_str()
}
else {
qDebug() << "#FailedCopy: Windows file copy failed outright" << src;
}
}
#endif
// copy failed
return BackupResult::IOError;
}
// copy success
return BackupResult::Success;
}
更新:
正如@john 的评论中提到的,我在指向源文件的目标文件方面遇到了问题,这显然不能正常工作。
解决了这个问题后,这突出显示了另一个错误 ERROR_INVALID_NAME:
ERROR_INVALID_NAME
123 (0x7B)
The filename, directory name, or volume label syntax is incorrect.
我通过发布的解决方案解决了这个问题。
这个函数有问题:
// not used
static const wchar_t* toLPCWSTR(QString s)
{
std::wstring dstWString = s.toStdWString();
const wchar_t* localC_src = dstWString.c_str();
return localC_src;
}
您正在返回一个已被解构的字符串的原始指针。
因此,这两行:
const wchar_t* localC_src = toLPCWSTR(src);
const wchar_t* localC_dst = toLPCWSTR(dst);
是未定义的行为,但最可能的结果是 localC_src
和 localC_dst
指向释放的内存。
最好保留你用 around 转换的 std::wstring
,同时仍然引用里面的指针
std::wstring strSrc = src.toStdWString();
std::wstring strDst = dst.toStdWString();
const wchar_t* localC_src = strSrc.c_str();
const wchar_t* localC_dst = strDst.c_str();