Windows 永远不会包含临时文件的非 ASCII 字符的目录?

Windows directory that will never contain non-ASCII characters for temp file?

在 Windows 上使用 MinGW 7.3.0,由于 Windows 限制,Hunspell 无法从具有非 ASCII 字符的位置加载字典文件。我已经尝试了所有方法[1],现在我正在将文件复制到没有 ASCII 字符的路径,然后再将其提供给 Hunspell。将其复制到什么位置比较好?

[1]

  1. Windows 需要 wchar_t 支持 std::iostream.open() 才能正常工作,而 MinGW 没有实现
  2. std::filesystem 可以解决这个问题,但只适用于 GCC 8
  3. Hunspell 坚持自己加载文件,无法将读取的文件作为字符串传递给它

“自然”适合使用用户选择的临时目录(或其子目录)(参见 %temp%GetTempPath())。但是,默认为包含用户名的内容(可以包含“non-ASCII”字符;例如 c:\users\Ø¥Ć¼\AppData\LocalLow\Temp)或任意内容(关于字符集)。

所以您最好选择一些目录,

a) 从一开始就不包含 off-limits 个字符。例如,您自己选择的 C:\ProgramData 下的目录(例如应用程序名称)不包含 non-ASCII 个字符。

b) 让用户决定将这些文件放在哪里,并确保不允许输入仅包含允许字符的路径。

c) 将 "short path name" 传递给 Hunspell,它不应包含 non-ASCII 字符以与 FAT 文件系统特征兼容。例如,c:\temp\Ø¥Ć¼ 的短路径名称是 c:\temp1D~1.

您可以使用 cmd.exe /c dir /x 查看目录的简称:

C:\temp>dir /x
...    
19.07.2019  15:30    <DIR>                       .
19.07.2019  15:30    <DIR>                       ..
19.07.2019  15:30    <DIR>          571D~1       Ø¥Ć¼

如何从 MinGW 调用 GetShortPathName Win32 API 我不知道,但我认为这是可能的。

还要确保查看 MSDN 页面以了解上述特征函数,例如并非所有地方都支持短名称(例如 SMB + 请参阅下面的评论)。

看起来 C:\Windows\Temp 仍然是您可以写给自己的有效路径。

来自 this bug tracker

In WIN32 environment, use UTF-8 encoded paths started with the long path prefix \?\ to handle system-independent character encoding and very long path names (without the long path prefix Hunspell will use fopen() with system-dependent character encoding instead of _wfopen()).

所以实际的解决方案似乎是:

  1. 调用GetFullPathNameW to normalize the path. Required because paths with long path prefix\?\都传递给NTAPI不变。
  2. L"\\?\" 添加到规范化路径(由于 C 字符串文字要求,反斜杠加倍)。
  3. 对于 UNC 路径,您必须直接使用 "UNC" 设备(即 L"\\server\share"L"\\?\UNC\server\share"(感谢 eryksun)
  4. 以 UTF-8 编码路径,例如。 G。使用 WideCharToMultiByte()CP_UTF8.
  5. 将最终的 UTF-8 编码路径传递给 Hunspell。