V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
archdevil
V2EX  ›  程序员

请教一个 C++操作文件的问题

  •  
  •   archdevil · 2017-07-29 19:04:04 +08:00 · 3524 次点击
    这是一个创建于 2463 天前的主题,其中的信息可能已经有所发展或是发生改变。
    我有一个文件,D:\x・x\1.txt
    x 与 x 之间那个点是全角符号,我试了很多 API 都无法识别这个路径
    fopen, CFindFile,GetFileAttributesW 等函数都尝试过,都无法识别路径。
    请问要怎么解决这个编码问题
    19 条回复    2017-07-30 10:36:28 +08:00
    auser
        1
    auser  
       2017-07-29 19:15:23 +08:00   ❤️ 1
    貌似是 Windows 环境下的,不懂,胡乱猜测一下:源代码文件编码经过编译后的表示跟 FileSystem 用的不一样导致的吧。
    正解:从源头上解决这个问题,文件名用普通常用模式。
    alqaz
        2
    alqaz  
       2017-07-29 19:15:58 +08:00
    可以改文件名吗?还有,如果文件名写在代码里,试着看下代码的编码。
    archdevil
        3
    archdevil  
    OP
       2017-07-29 19:24:04 +08:00
    我知道改文件名就行了,可是我就是想知道 windows 下的 vs 编译器里怎么解决这个问题。
    windows 自身能识别这些目录和文件,为什么他提供的 API 就不行呢
    veelog
        4
    veelog  
       2017-07-29 19:29:09 +08:00 via iPhone
    试试遍历目录,把这个文件名二进制数据发音,出来,在打印你自己定义的文件名对比下
    nifury
        5
    nifury  
       2017-07-29 19:36:26 +08:00
    fopen 或许是对 unicode 支持不好吧,毕竟是 ansi 版本
    GetFileAttributesW 和 CreateFileW 是可以的
    Librazy
        6
    Librazy  
       2017-07-29 19:58:42 +08:00
    GetFileAttributesExW + \\?\ 试试?
    wevsty
        7
    wevsty  
       2017-07-29 20:19:48 +08:00
    跟楼上说的一样,用 Unicode 版本的 API,你这个估计是编码的问题。
    可以用 API 枚举一下文件夹,然后看看枚举出来的路径和你自己输入的有什么区别
    hobochen
        8
    hobochen  
       2017-07-29 20:23:15 +08:00 via Android
    windows 下的路径为 UTF-16 编码
    ysc3839
        9
    ysc3839  
       2017-07-29 20:24:13 +08:00 via Android
    Win 下 fopen 是 ANSI 的,肯定不行。换用 wfopen (不知有没有记错),或者 CreateFileW。另外试试把代码文件保存成 UTF-8 编码。
    RLib
        10
    RLib  
       2017-07-29 20:26:46 +08:00
    楼上的, 注意 LZ 说的 GetFileAttributesW 已经就是宽字符版本了
    baixiangcpp
        11
    baixiangcpp  
       2017-07-29 20:43:13 +08:00
    @ysc3839 用了 ANSI,当然存为 GBK 啊
    baixiangcpp
        12
    baixiangcpp  
       2017-07-29 20:50:02 +08:00
    字符串字面量编码是你源文件的编码。

    1.路径编码是 GBK 的话,就用 ANSI 的函数 fopen,CreateFile
    2.路径编码是 Unicode ( UCS2 ) 的话,就用 CreateFileW
    3.utf-8 保存的话,glib 的那套函数是 utf8 版本的
    ysc3839
        13
    ysc3839  
       2017-07-29 21:24:20 +08:00
    @baixiangcpp GBK 编码可能没有这个字符
    FanWall
        14
    FanWall  
       2017-07-29 21:25:53 +08:00
    一律用宽字符就好了
    ysc3839
        15
    ysc3839  
       2017-07-29 21:30:11 +08:00
    #include <stdio.h>
    #include <wchar.h>

    int main()
    {
    FILE *f = fopen("C:\\Users\\Richard\\Desktop\\x・x\\1.txt", "r");
    printf("0x%X\n", f);
    if (f)
    fclose(f);

    f = _wfopen(L"C:\\Users\\Richard\\Desktop\\x・x\\1.txt", L"r");
    printf("0x%X\n", f);
    if (f)
    fclose(f);
    return 0;
    }

    Output:
    0x0
    0x1014FF0
    baixiangcpp
        16
    baixiangcpp  
       2017-07-30 01:19:19 +08:00
    @ysc3839 你知道 fopen 是 ANSI 的函数,还用 UTF8 保存,这不是故意的找错吗
    yksoft1
        17
    yksoft1  
       2017-07-30 01:21:46 +08:00
    你碰上了 GBK 编码的缺陷之一(不支持日文编码中的那个点以及半角片假名)。这种情况 ANSI 版的 fopen 是不能用的。
    soratadori
        18
    soratadori  
       2017-07-30 03:53:34 +08:00
    我想说......请注意你的 cpp 文件编码格式,你要想用 wfopen 之类的支持 unicode 的函数,你传进去的字符也必须是 unicode。
    RLib
        19
    RLib  
       2017-07-30 10:36:28 +08:00   ❤️ 1
    这贴怎么又上来了...
    @baixiangcpp 编码用 UTF8 保存并没有错, 还能保证跨平台不出问题, 楼主的例子在于如果不保存成 UTF 系列编码一开始信息就丢失了, 编译器读到的只是 0x3f 这一个字节.
    另外编译器编译时会完成转换, 最后和源文件编码无关:
    "・" 编译后无论源码是什么格式都是 ANSI 编码, 在 ANSI 被设定 936 的情况下它是 0x3f
    L"・" UTF-16 编码
    u8"・" UTF-8 编码
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   2968 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 26ms · UTC 13:16 · PVG 21:16 · LAX 06:16 · JFK 09:16
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.