繁体   English   中英

对于非ASCII字符,GetFileAttributeW失败

[英]GetFileAttributeW fails for non-ASCII characters

所以我试图检查给定的文件是否存在。 这个答案后我尝试了GetFileAttributesW 它适用于任何ascii输入,但它不能用于ß,ü和á(以及我怀疑的任何其他非ascii字符)。 我为它们获取了文件名的ERROR_FILE_NOT_FOUND和带有它们的路径名的ERROR_PATH_NOT_FOUND ,正如人们所预期的那样,如果它们不存在的话。

我100%肯定他们做到了。 我花了15分钟来复制文件名,以免拼写错误并使用文字来避免任何不良输入。 我找不到任何错误。

由于所有这些字符都是非ascii字符,我不再尝试,因为我怀疑我可能已经搞砸了编码。 我只是无法发现它。 有什么我想念的吗? 我链接到Kernel32.lib

谢谢!

#include <stdio.h>
#include <iostream>
#include <string>
#include "Windows.h"


void main(){
    while(true){
        std::wstring file_path;
        std::getline(std::wcin, file_path);

        DWORD dwAttrib = GetFileAttributesW(file_path.data());
        if(dwAttrib == INVALID_FILE_ATTRIBUTES){
            printf("error: %d\n", GetLastError());
            continue;
        }

        if(!(dwAttrib & FILE_ATTRIBUTE_DIRECTORY))
            printf("valid!\n");
        else
            printf("invalid!\n");
    }
}

在Windows上的控制台程序中使Unicode工作得很好是非常困难的,所以让我们首先去掉它的这个方面(现在)。

修改您的程序,使其如下所示:

#include <cstdio>
#include <iostream>
#include <string>
#include "Windows.h"

int main() {
    std::wstring file_path = L"fooß.txt";

    DWORD dwAttrib = GetFileAttributesW(file_path.data());
    if (dwAttrib == INVALID_FILE_ATTRIBUTES)
        printf("error: %d\n", GetLastError());

    if (!(dwAttrib & FILE_ATTRIBUTE_DIRECTORY))
        printf("valid!\n");
    else
        printf("invalid!\n");

    return 0;
}

即使您使用的是UTF-8,也要确保使用字节顺序标记(BOM)保存此文件。 Windows应用程序,包括Visual Studio和编译器,可能非常挑剔。 如果编辑器不这样做,请使用Visual Studio编辑文件,然后使用“另存为”,单击“保存”按钮旁边的向下箭头,选择“使用编码”。 在“高级保存选项”对话框中,选择“Unicode(带签名的UTF-8) - 代码页65001”。

确保当前文件夹中有一个名为fooß.txt的文件。 我强烈建议使用GUI程序来创建此文件,如记事本或资源管理器。

这个程序有效。 如果仍然收到文件未找到消息,请检查以确保临时文件位于工作目录中或更改程序以使用绝对路径。 如果使用绝对路径,请使用反斜杠并确保它们都已正确转义。 检查拼写错误,扩展名等。此代码确实有效。

现在,如果从标准输入中获取文件名:

    std::wstring file_path;
    std::getline(std::wcin, file_path);

你在控制台窗口中输入fooß.txt ,你可能会发现它不起作用。 如果你查看调试器,你会看到应该是ß的字符是别的东西。 对我来说,它是á ,但如果您的控制台代码页是其他的话,它可能会有所不同。

ß是Unicode中的U + 00DF。 在Windows 1252(美国Windows用户最常见的代码页)中,它是0xDF,因此看起来似乎没有转换问题的可能性。 但控制台窗口(默认情况下)使用OEM代码页。 在美国,常见的OEM代码页是437.因此,当我尝试在控制台中键入ß时,实际上编码为0xE1。 惊喜! 这与á的Unicode值相同。 如果您设法输入值为0xDF的字符,您将看到对应于您在原始问题中报告的块字符。

你会认为(好吧, 认为)从std::wcin请求输入会做任何必要的转换。 但它没有,并且可能存在一些传统的向后兼容性原因。 您可以尝试使用“正确的”代码页填充流,但这变得复杂,我从未打扰过尝试使其工作。 我只是停止尝试在控制台上使用除ASCII以外的任何东西。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM