无法使用 CLion 打开文件名中包含 unicode 字符的文件
Can't open a file with unicode chars in the file name using CLion
我在打开名称中包含 Unicode 字符的文件时遇到问题。
我在桌面上创建了一个只有几行文本的文件。
c:\users\james\desktop\你好世界.txt
编辑:我正在使用 CLion。 CLion 正在以 unicode 格式传递参数。
当我将该字符串放入 Windows 运行 对话框时,它会找到文件并打开它。
不过,有趣的是,我通过调用 CommandLineToArgvW:
在文件夹名称中得到了双 L'\'
L'\'
L"c:\\users\\james\\desktop\\你好世界.txt"
所以我写了一个小程序来将文件名复制到另一个 wchar_t *
并去掉斜杠。还是不行。
errno == 2
和 f == NULL
.
size_t filename_max_len = wcslen(filename);
//strip double slashes
wchar_t proper_filename[MAX_PATH + 1];
wchar_t previous = L'[=10=]';
size_t proper_filename_location = 0;
for(int x = 0; x < filename_max_len; ++x)
{
if(previous == L'\' && filename[x] == L'\')
continue;
previous = filename[x];
proper_filename[proper_filename_location++] = filename[x];
}
proper_filename[proper_filename_location] = L'[=10=]';
//Read in binary mode to prevent the C system from screwing with line endings
FILE *f = _wfopen(proper_filename, L"rb");
int le = errno;
if (f == NULL)
{
perror(strerror(le));
if(le == ERROR_FILE_NOT_FOUND)
{
return DUST_ERR_FILE_NOT_FOUND;
}
else {
return DUST_ERR_COULD_NOT_OPEN_FILE;
}
}
我已经找到问题了。我的直觉是正确的。 CLion 似乎正在提供 unicode 作为程序的输入。使用 Windows 运行 对话框并将其作为参数传递给我的程序,我能够毫无问题地打开和处理文件。
我的第一个猜测是 228、189、160 代表编码为 UTF-8 字节序列的文件名的第一个字符,因为它看起来像这样的序列。 E4 BD A0(228,189,160)解码为U+4F60,确实是第一个字符对应的Unicode码位。
我修改了 中 main
的输出部分,将每个参数打印为十六进制编码的字节序列。我将你的路径作为参数复制并粘贴到程序中,汉字在 UTF-8 中编码为:
E4 BD A0
E5 A5 BD
E4 B8 96
E7 95 8C
您的评论提到的数字略有不同(特别是 8211/U+2013、8226/U+2022 和 338/U+0152)。查看代码页 Windows 1250 和 Windows 1252,两个代码页中的字节 0x96、0x95 和 0x8C 分别与 U+2013、U+2022 和 U+0152 完全对应。我猜你的原始程序在遇到 Unicode 输入时在某处出错了(你 是 使用 GetCommandLineW
并将其传递给 CommandLineToArgvW
,对吗?)
这是我编辑的输出截图,以突出显示相关的字符序列(¥
字形应该是 \
字形,但我使用 code page 932 cmd.exe):
我在打开名称中包含 Unicode 字符的文件时遇到问题。 我在桌面上创建了一个只有几行文本的文件。
c:\users\james\desktop\你好世界.txt
编辑:我正在使用 CLion。 CLion 正在以 unicode 格式传递参数。
当我将该字符串放入 Windows 运行 对话框时,它会找到文件并打开它。
不过,有趣的是,我通过调用 CommandLineToArgvW:
在文件夹名称中得到了双 L'\'
L'\'
L"c:\\users\\james\\desktop\\你好世界.txt"
所以我写了一个小程序来将文件名复制到另一个 wchar_t *
并去掉斜杠。还是不行。
errno == 2
和 f == NULL
.
size_t filename_max_len = wcslen(filename);
//strip double slashes
wchar_t proper_filename[MAX_PATH + 1];
wchar_t previous = L'[=10=]';
size_t proper_filename_location = 0;
for(int x = 0; x < filename_max_len; ++x)
{
if(previous == L'\' && filename[x] == L'\')
continue;
previous = filename[x];
proper_filename[proper_filename_location++] = filename[x];
}
proper_filename[proper_filename_location] = L'[=10=]';
//Read in binary mode to prevent the C system from screwing with line endings
FILE *f = _wfopen(proper_filename, L"rb");
int le = errno;
if (f == NULL)
{
perror(strerror(le));
if(le == ERROR_FILE_NOT_FOUND)
{
return DUST_ERR_FILE_NOT_FOUND;
}
else {
return DUST_ERR_COULD_NOT_OPEN_FILE;
}
}
我已经找到问题了。我的直觉是正确的。 CLion 似乎正在提供 unicode 作为程序的输入。使用 Windows 运行 对话框并将其作为参数传递给我的程序,我能够毫无问题地打开和处理文件。
我的第一个猜测是 228、189、160 代表编码为 UTF-8 字节序列的文件名的第一个字符,因为它看起来像这样的序列。 E4 BD A0(228,189,160)解码为U+4F60,确实是第一个字符对应的Unicode码位。
我修改了 main
的输出部分,将每个参数打印为十六进制编码的字节序列。我将你的路径作为参数复制并粘贴到程序中,汉字在 UTF-8 中编码为:
E4 BD A0
E5 A5 BD
E4 B8 96
E7 95 8C
您的评论提到的数字略有不同(特别是 8211/U+2013、8226/U+2022 和 338/U+0152)。查看代码页 Windows 1250 和 Windows 1252,两个代码页中的字节 0x96、0x95 和 0x8C 分别与 U+2013、U+2022 和 U+0152 完全对应。我猜你的原始程序在遇到 Unicode 输入时在某处出错了(你 是 使用 GetCommandLineW
并将其传递给 CommandLineToArgvW
,对吗?)
这是我编辑的输出截图,以突出显示相关的字符序列(¥
字形应该是 \
字形,但我使用 code page 932 cmd.exe):