Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/windows/17.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 在Windows上,对于包含奇怪字符的路径,stat和GetFileAttributes失败_C++_Windows - Fatal编程技术网

C++ 在Windows上,对于包含奇怪字符的路径,stat和GetFileAttributes失败

C++ 在Windows上,对于包含奇怪字符的路径,stat和GetFileAttributes失败,c++,windows,C++,Windows,下面的代码演示了当路径包含一些奇怪(但有效)的ASCII字符时,stat和GetFileAttributes如何失败。 作为解决方法,我将使用8.3 DOS文件名。但当驱动器禁用了8.3个名称时,这不起作用。 (8.3使用fsutil命令禁用名称:fsutil行为集disable8dot3 1) 在这种情况下,可以让stat和/或GetFileAttributes工作吗? 如果不是,是否有其他方法确定路径是目录还是文件 #include "stdafx.h" #include <sys/

下面的代码演示了当路径包含一些奇怪(但有效)的ASCII字符时,stat和GetFileAttributes如何失败。 作为解决方法,我将使用8.3 DOS文件名。但当驱动器禁用了8.3个名称时,这不起作用。 (8.3使用fsutil命令禁用名称:fsutil行为集disable8dot3 1)

在这种情况下,可以让stat和/或GetFileAttributes工作吗? 如果不是,是否有其他方法确定路径是目录还是文件

#include "stdafx.h"

#include <sys/stat.h>
#include <string>
#include <Windows.h>
#include <atlpath.h>

std::wstring s2ws(const std::string& s)
{
    int len;
    int slength = (int)s.length() + 1;
    len = MultiByteToWideChar(CP_ACP, 0, s.c_str(), slength, 0, 0);
    wchar_t* buf = new wchar_t[len];
    MultiByteToWideChar(CP_ACP, 0, s.c_str(), slength, buf, len);
    std::wstring r(buf);
    delete[] buf;
    return r;
}

// The final characters in the path below are 0xc3 (Ã) and 0x3f (?).
// Create a test directory with the name à and set TEST_DIR below to your test directory.
const char* TEST_DIR = "D:\\tmp\\VisualStudio\\TestProject\\ConsoleApplication1\\test_data\\Ã"; 

int main()
{
    std::string testDir = TEST_DIR;

    // test stat and _wstat
    struct stat st;
    const auto statSucceeded = stat(testDir.c_str(), &st) == 0;
    if (!statSucceeded)
    {
        printf("stat failed\n");
    }

    std::wstring testDirW = s2ws(testDir);

    struct _stat64i32 stW;
    const auto statSucceededW = _wstat(testDirW.data(), &stW) == 0;
    if (!statSucceededW)
    {
        printf("_wstat failed\n");
    }

    // test PathIsDirectory
    const auto isDir = PathIsDirectory(testDirW.c_str()) != 0;
    if (!isDir)
    {
        printf("PathIsDirectory failed\n");
    }

    // test GetFileAttributes
    const auto fileAttributes = ::GetFileAttributes(testDirW.c_str());
    const auto getFileAttributesWSucceeded = fileAttributes != INVALID_FILE_ATTRIBUTES;
    if (!getFileAttributesWSucceeded)
    {
        printf("GetFileAttributes failed\n");
    }

    return 0;
}
#包括“stdafx.h”
#包括
#包括
#包括
#包括
std::wstring s2ws(const std::string&s)
{
内伦;
int slength=(int)s.length()+1;
len=MultiByteToWideChar(CP_ACP,0,s.c_str(),slength,0,0);
wchar_t*buf=新的wchar_t[len];
MultiByteToWideChar(CP_ACP,0,s.c_str(),slength,buf,len);
标准:WSTR环(buf);
删除[]buf;
返回r;
}
//下面路径中的最后字符是0xc3(Ã)和0x3f(?)。
//创建一个名为Ã的测试目录,并将下面的test_DIR设置为您的测试目录。
const char*TEST_DIR=“D:\\tmp\\VisualStudio\\TestProject\\ConsoleApplication1\\TEST_data\\Ô;
int main()
{
std::string testDir=TEST_DIR;
//测试状态和_wstat
结构统计;
const auto statsucceeed=stat(testDir.c_str(),&st)==0;
如果(!statsucceed)
{
printf(“stat失败\n”);
}
std::wstring testDirW=s2ws(testDir);
结构stat64i32 stW;
const auto statSucceededW=_wstat(testDirW.data(),&stW)==0;
如果(!statSucceededW)
{
printf(“\u wstat失败\n”);
}
//测试路径目录
const auto isDir=pathidirectory(testDirW.c_str())!=0;
if(!isDir)
{
printf(“路径目录失败\n”);
}
//测试GetFileAttributes
const auto fileAttributes=::GetFileAttributes(testDirW.c_str());
const auto getFileAttributesWSucceeded=文件属性!=无效的文件属性;
如果(!getFileAttributesWSucceeded)
{
printf(“GetFileAttributes失败\n”);
}
返回0;
}

您遇到的问题来自于使用MultiByteToWideChar函数。使用CP_ACP可以默认为不支持某些字符的代码页。如果将默认系统代码页更改为UTF8,代码将正常工作。由于您无法告诉客户要使用什么代码页,因此可以使用第三方库(如Unicode国际组件)将主机代码页转换为UTF16


我使用控制台代码页65001和VS2015运行了您的代码,您的代码按编写的方式运行。我还添加了正数printfs,以验证它是否有效。

不要以窄字符串文字开始并尝试转换它,而要以宽字符串文字开始—一个表示实际文件名的文字。您可以使用十六进制转义序列来避免对源代码编码的任何依赖

如果实际代码不使用字符串文字,则最佳分辨率取决于具体情况;例如,如果正在从文件读取文件名,则需要确保知道文件的编码方式,并相应地执行转换

如果实际代码从命令行参数读取文件名,则可以使用wmain()而不是main()将参数作为宽字符串获取。

“奇怪(但有效)的ASCII字符”--ASCII仅定义0x00到0x7f范围内的字符。0xc3不在ASCII的范围内。Win特定的解决方法:使用
wchar\u t
而不是
char
(或者更好:),还显式使用(和)(无
s2ws
wstring
,…)。