gpt4 book ai didi

C++ 和 NTFS 文件 : pathname VS opening

转载 作者:行者123 更新时间:2023-11-27 23:19:16 25 4
gpt4 key购买 nike

这是这个问题的扩展:fstream not opening files with accent marks in pathname

问题如下:打开一个简单的 NTFS 文本文件的程序在路径名中带有重音符号(例如àò、. ..).在我的测试中,我使用了一个路径名为 I:\università\foo.txt 的文件(universitàuniversity 的意大利语翻译)

下面是测试程序:

#include <iostream>
#include <fstream>
#include <string>
#include <cstdio>
#include <errno.h>
#include <Windows.h>

using namespace std;

LPSTR cPath = "I:/università/foo.txt";
LPWSTR widecPath = L"I:/università/foo.txt";
string path("I:/università/foo.txt");

void tryWithStandardC();
void tryWithStandardCpp();
void tryWithWin32();

int main(int argc, char **argv) {
tryWithStandardC();
tryWithStandardCpp();
tryWithWin32();

return 0;
}

void tryWithStandardC() {
FILE *stream = fopen(cPath, "r");

if (stream) {
cout << "File opened with fopen!" << endl;
fclose(stream);
}

else {
cout << "fopen() failed: " << strerror(errno) << endl;
}
}

void tryWithStandardCpp() {
ifstream s;
s.exceptions(ifstream::failbit | ifstream::badbit | ifstream::eofbit);

try {
s.open(path.c_str(), ifstream::in);
cout << "File opened with c++ open()" << endl;
s.close();
}

catch (ifstream::failure f) {
cout << "Exception " << f.what() << endl;
}
}

void tryWithWin32() {

DWORD error;
HANDLE h = CreateFile(cPath, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);

if (h == INVALID_HANDLE_VALUE) {
error = GetLastError();
cout << "CreateFile failed: error number " << error << endl;
}

else {
cout << "File opened with CreateFile!" << endl;
CloseHandle(h);
return;
}

HANDLE wideHandle = CreateFileW(widecPath, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);

if (wideHandle == INVALID_HANDLE_VALUE) {
error = GetLastError();
cout << "CreateFileW failed: error number " << error << endl;
}

else {
cout << "File opened with CreateFileW!" << endl;
CloseHandle(wideHandle);
}
}

源文件以UTF-8编码保存。我正在使用 Windows 8。

这是用VC++(Visual Studio 2012)编译程序的输出

fopen() failed: No such file or directory
Exception ios_base::failbit set
CreateFile failed: error number 3
CreateFileW failed: error number 3

这是使用 MinGW g++ 的输出

fopen() failed: No such file or directory
Exception basic_ios::clear
CreateFile failed: error number 3
File opened with CreateFileW!

那么让我们来回答问题:

  1. 为什么 fopen() 和 std::ifstream 在 Linux 中可以进行类似的测试,但在 Windows 中却不行?
  2. 为什么 CreateFileW() 只能用 g++ 编译?
  3. 是否存在 CreateFile 的跨平台替代方案?

我希望打开一个带有generic 路径名的generic 文件可以在不需要特定于平台的代码的情况下完成,但我不知道该怎么做。

提前致谢。

最佳答案

你写:

“The source file is saved with UTF-8 encoding.”

好吧,如果您使用的是 g++ 编译器,那一切都很好(到目前为止),它以 UTF-8 作为其默认的基本源字符集。但是,Visual C++ 默认假定源文件是用 Windows ANSI 编码的,除非另有明确说明。因此,请务必确保它在开头有一个 BOM(字节顺序标记),据我所知,它未记录在案 - 导致 Visual C++ 将其视为使用 UTF-8 编码。

然后你问,

“1. Why fopen() and std::ifstream works in a similar test in Linux but they don't in Windows?”

对于 Linux,它可能可以工作,因为 (1) 现代 Linux 是面向 UTF-8 的,所以如果文件名看起来相同,它可能与中的相同的 UTF-8 编码文件名相同源代码,以及 (2) 在 *nix 中,文件名只是字节序列,而不是字符序列。这意味着无论它看起来如何,如果您传递相同的字节序列、相同的值,那么您就有一个匹配项,否则就没有匹配项。

相比之下,在 Windows 中,文件名是可以用多种方式编码的字符序列。

在您的情况下,源代码中的 UTF-8 编码文件名在可执行文件中存储为 Windows ANSI(是的,使用 Visual C++ 构建的结果取决于 Windows 中选定的 ANSI 代码页,据我所知知道是无证)。然后这个 gobbledegook 字符串向下传递到例程层次结构并转换为 UTF-16,这是 Windows 中的标准字符编码。结果与文件名完全不匹配。


你进一步问,

“2. Why CreateFileW() works only compiling with g++?”

大概是因为您没有在源代码文件的开头包含 BOM(见上文)。

有了 BOM,一切都可以很好地与 Visual C++ 配合使用,至少在 Windows 7 中是这样:

File opened with fopen!File opened with c++ open()File opened with CreateFile!

最后,你问,

“3. Does exist a cross-platform alternative to CreateFile?”

不是真的。有升压文件系统。但是虽然它的第 2 版确实有针对标准库的基于有损窄字符的编码的解决方法,但该解决方法在第 3 版中被删除,它只使用 Visual C++ 标准库的扩展,其中 Visual C++ 实现提供流构造函数和 open 的宽字符参数版本。即,至少据我所知(我最近没有检查是否已修复问题),Boost 文件系统通常只适用于 Visual C++,不适用于例如g++——尽管它适用于无问题字 rune 件名。

v2 的解决方法是尝试转换为 Windows ANSI(由 GetACP 函数指定的代码页),如果不起作用,请尝试 GetShortPathName,实际上保证可以用 Windows ANSI 表示。

Boost 文件系统中的解决方法被删除的部分原因是,据我所知,原则上用户可以关闭 Windows 短名称功能,至少在 Windows Vista 和更早版本中是这样。然而,这不是一个实际问题。这只是意味着如果用户因故意对系统进行脑叶切除术而遇到问题,则有一个简单的修复方法(即重新打开它)。

关于C++ 和 NTFS 文件 : pathname VS opening,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14527845/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com