【问题标题】:Using fopen on a directory on windows在 Windows 上的目录上使用 fopen
【发布时间】:2016-09-02 13:20:21
【问题描述】:

当使用 fopen 和 ifstream.open() 打开目录作为文件时,我试图从 errno 中获取正确的错误代码。我期待 EISDIR,我得到 EACCES。

我正在 Windows 7 x64 上使用 MSVC 12.0 工具链编译(和执行)。

我一直在阅读文章 (https://gehrcke.de/2011/06/reading-files-in-c-using-ifstream-dealing-correctly-with-badbit-failbit-eofbit-and-perror/),作者得到了输出“stream failbit (or badbit).error state: Is a directory”。

我使用 GCC 4.6(或更高版本,不确定 atm)编译了作者文件,并在传递目录作为参数时也得到了 EACCES。

我知道没有简单的方法来判断磁盘对象是否是 Windows 上的目录,所以没有得到 EISDIR 也不足为奇。

有什么可以做的(就是在 Windows 上获取 EISDIR)? 是否有其他 errno 以类似(意外)的方式表现?

【问题讨论】:

  • 请照常提供minimal reproducible example。您也不能将目录作为文件打开。
  • 我认为你不走运 - 我找不到 Microsoft C 库中引用的 EINVALis_a_directory 符号(我检查了 VS 12.0 和通用 CRT 作为VS 14.0 使用)除了定义本身之外的任何地方,即它们存在但未使用。替代方案(MinGW 等)链接到 msvcrt.dll,您已经确认它的行为也不符合您的要求。
  • 我认为使用 errno 检查设备对象是文件还是目录不是一个好的选择。由于此方法依赖于平台和编译器,因此不稳定,并且 C++ 标准没有说明处理 ifstream 错误的行为。
  • “很难判断磁盘对象是否是 Windows 上的目录”- 有一个相当简单的 GetFileAttributes( object ) & FILE_ATTRIBUTE_DIRECTORY。而MSVC有_stat()_fstat,见st_mode & _S_IFDIR
  • @πάνταῥεῖ 请使用 OP 链接中的源代码。如果你得到不同的结果,我很想知道。

标签: c++ windows file


【解决方案1】:

Microsoft 的 C 运行时库定义但不使用 EISDIR 符号。所以你不会从他们那里得到那个错误代码。要获得其他问题的答案,您需要查看 C 库源代码。它随 Visual Studio 一起提供,如果是 Visual Studio 2015 及更高版本,则随 Windows SDK 一起提供。

在使用通用 CRT 的 Visual Studio 2015 (14.0) 中,您需要的文件名为 errno.cpp,它包含在 Windows SDK 中,我在 c:\Program Files (x86)\Windows Kits\10\Source\10.0.10586.0\ucrt\misc\errno.cpp 中有它。

在 Visual Studio 2013 (12.0) 中,您需要的文件名为 dosmap.c,它包含在 Visual Studio 安装目录的 VC 子目录中,我在 C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\crt\src\dosmap.c 中。

这两个文件都包含一个错误表,将操作系统错误代码映射到 C 库错误代码。您可以使用它来确认特定映射是否符合您的期望。

【讨论】:

  • 所以在 Windows 上没有 EISDIR...感谢您的澄清。
【解决方案2】:

fopen 函数不是 Windows API 的一部分;它来自某些给定 C 或 C++ 开发环境的运行时支持库。

EISDIR 错误适用于为 Cygwin 构建并随 Cygnal 一起提供的 C 应用程序:

c:\users\kaz>txr
This is the TXR Lisp interactive listener of TXR 148.
Use the :quit command or type Ctrl-D on empty line to exit.
1> (open-file ".")
#<file-stream . 6fffff00738>
2> (get-string *1)
** error reading #<file-stream . 6fffff00738>: 21/"Is a directory"
** during evaluation at expr-2:1 of form (get-string *1)
3>

该语言中的open-file函数使用fopen,而get-string最终依赖于C语言的stdio.h函数。 fopen 成功,但随后的输入尝试收到 EISDIR 错误。 (映射到与 Linux 和其他平台上相同的传统 21 代码)。这变成了一个例外。 "Is a directory" 字符串来自strerror

您只需要一个功能更丰富的 C 运行时库,它比 Microsoft Visual Studio 提供的微不足道的产品支持更好的 POSIX。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-11-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多