在窗口中用UTF8字符串打开文件名



当我使用opencv的API cvLoadImage(const char *filename, int iscolor)时,它接受const char *作为文件名。当文件名不是ASCII字符时,我尝试将其转换为UTF8字符串。它失败了,因为在cvLoadImage()中调用的fopen()无法将文件名的字符从字面上解释为ASCII字符串。如果试图打开文件名,我可能会使用_wfopen(),但如果在第三方库中调用fopen(),有什么方法可以处理这个问题吗?非常感谢。

使用GetShortPathName。它将返回文件的旧名称(8.3),您应该能够将其转换为char*,因为它不应该包含任何非ASCII字符。

我刚刚用一些特定语言的字符测试了它,它就像我描述的那样工作。我已经使用fopen成功地从C:łęłęłąóąóą.tsttgbb打开了一个文件。

setlocale(LC_ALL, ".65001");
fopen(u8"中文路径.txt", "rb"); //window7(中文) vs2017 ok

快速搜索一无所获,但人们表示无法完成。如果你不能改变cvLoadImage(这是合理的,你不想搞砸它),你可以试着欺骗它

  1. 您可以使用CreateSymbolicLink创建指向该文件的链接。不过,我不确定它是否能工作,因为MKLINK命令行实用程序需要管理权限
  2. 如果无法创建符号链接,则可以始终使用仅ASCII名称将文件复制到其他位置
  3. 如果你真的不想复制文件,并且符号链接不起作用,你可以创建一个文件代理-创建一个仅具有ASCII名称的命名管道,并将从管道读取的每个数据转换为从文件读取

不过,我会选择选项1或2——简单得多。

这是对这个问题的最新贡献。我查看了运行库的来源(微软很乐意提供),发现我可以用以下代码替换fopen用来映射ANSI字符串的例程(只需将其链接到你的exe中,它就会替换运行库中的例程)。

列出的版本适用于使用v141_xp工具包的Visual Studio 2017。我还没有在其他版本中测试过它,但我想可能需要一些小的更改(比如例程本身的名称)。如果有问题的库是一个DLL,它当然不会工作。随心所欲。

#ifdef _DEBUG
    #define _NORMAL_BLOCK   1
    #define _CRT_BLOCK      2
    #define _malloc_crt(s)  (_malloc_dbg  (s, _CRT_BLOCK, __FILE__, __LINE__))
#else
    #define _malloc_crt     _malloc_base
#endif
// A hack to make fopen et al accept UTF8 strings (as at Visual Studio 2017), see:
//    D:Program Files (x86)Windows Kits10Source10.0.10240.0ucrtinternalstring_utilities.cpp
//    D:Program Files (x86)Windows Kits10Source10.0.10240.0ucrtinccorecrt_internal_traits.h
extern "C" BOOL __cdecl __acrt_copy_path_to_wide_string (char const* const path, wchar_t** const result)
{
    #if _MSC_VER != 1910
        #define STRINGIZE_HELPER(x) #x
        #define STRINGIZE(x) STRINGIZE_HELPER(x)
        __pragma (message (__FILE__ "(" STRINGIZE (__LINE__) ") : Error: Code not tested for this version of Visual Studio"));
    #endif
    assert (path);
    assert (result);
    // Compute the required size of the wide character buffer:
    int length = MultiByteToWideChar (CP_UTF8, 0, path, -1, nullptr, 0);
    assert (length > 0);
    *result = (wchar_t *) _malloc_crt (T2B (length));
    // Do the conversion:
    length = MultiByteToWideChar (CP_UTF8, 0, path, -1, *result, length);
    assert (length);
    return TRUE;
}

相关内容

  • 没有找到相关文章

最新更新