【问题标题】:Reading a directory读取目录
【发布时间】:2011-01-29 21:17:27
【问题描述】:

我正在尝试通过 K&R 解决锻炼问题;这是关于阅读目录的。此任务依赖于系统,因为它使用系统调用。在书中示例作者说他们的示例是为版本 7 和 System V UNIX 系统编写的,并且他们使用了头文件 中的目录信息,如下所示:

#ifndef DIRSIZ
#define DIRSIZ 14
#endif
struct direct {    /* directory entry */
    ino_t d_ino;           /* inode number */
    char d_name[DIRSIZ];   /* long name does not have '\0' */
};

在这个系统上,他们使用 'struct direct' 结合 'read' 函数来检索目录条目,它由文件名和 inode 号组成。

.....
struct direct dirbuf;    /* local directory structure */
while(read(dp->fd, (char *) &dirbuf, sizeof(dirbuf)
               == sizeof(dirbuf) {
    .....
}
.....

我想这在 UNIX 和 Linux 系统上运行良好,但我想做的是修改它以便它在 Windows XP 上运行。

Windows 中是否有一些结构,例如“struct direct”,所以我可以使用它 带有“读取”功能,如果有什么是标题名称,它在哪里 定义?

或者 Windows 需要完全不同的方法?

【问题讨论】:

    标签: c windows


    【解决方案1】:

    在 Windows 中没有这样的东西。如果要在 Windows 中枚举目录,则必须使用 FindFirstFile/FindNextFile API。

    【讨论】:

    • 不知何故,我不认为使 Windows 应用程序依赖于 Unix Emulation 库是新代码的良好设计选择。此外,MinGW 没有解决这个问题。您无法使用 MinGW 打开目录文件。 Cygwin 可能支持某些类似的东西,但 MinGW 不支持。
    • 好的,但是paleman 在问题中表示他正在解决K&R 的练习。所以我认为 Cygwin 是非常合理的选择。我同意你的观点,使用 Cygwin 制作生产应用程序不会是一个如此有益的想法。
    • 另外,感谢您指出 MinGW 在这里不起作用,我已经编辑了我的答案以更正那个。
    • 感谢您提供的链接,我可能会尝试使用 FindFirstFile/FindNextFile 函数。
    【解决方案2】:

    是的,这仅适用于 Linux/Unix。但是,如果您只是在玩耍,您可以使用 Cygwin 在 Windows 上构建使用此 Unix API 的程序。

    【讨论】:

    • 不,我不想使用 Cygwin,我在写第一篇文章时忘记写了,对不起。
    【解决方案3】:

    有趣的是,您使用的是 1978 年的 K&R 第一版,而不是第二版。第二版在本书的那一点上有不同的结构等。

    第一版中的代码不再适用于许多类 Unix 系统。很少有 Unix 机器具有将文件名限制为 14 个字符限制的文件系统,并且该代码仅适用于这些系统。具体来说,它不适用于 MacOS X (10.6.2) 或 Solaris (10) 或 Linux(SuSE Linux Enterprise Edition 10,内核 2.6.16.60-0.21-smp)。使用如下所示的测试代码,结果为:

    read failed: (21: Is a directory)
    

    当前版本的 POSIX 明确允许实现限制您可以对在目录上打开的文件描述符执行的操作。基本上,它可以用于 'fchdir()' 系统调用,也许还有一些亲戚,但仅此而已。

    要读取目录的内容,您必须使用opendir() 系列函数,然后使用readdir() 等。K&R 的第二版继续使用这些系统调用而不是原始的open() 和@ 987654330@等

    总而言之,30 多年前的代码与以前的工作方式不同,这并不奇怪。


    在 Windows 上,您可以使用 POSIX 子系统或类似 Cygwin 或 MingW 的仿真,在任何一种情况下,您都需要使用 opendir()readdir() 系列函数调用,而不是直接调用目录文件描述符上的open()read()

    或者您可以使用 BillyONeal 引用的本机 Windows API,FindFirstFile 和亲戚。


    测试代码:

    #include <unistd.h>
    #include <stdio.h>
    #include <string.h>
    #include <fcntl.h>
    #include <errno.h>
    
    int main()
    {
        int fd = open(".", O_RDONLY);
        if (fd != -1)
        {
            char buffer[256];
            ssize_t n = read(fd, buffer, sizeof(buffer));
            if (n < 0)
            {
                int errnum = errno;
                printf("read failed: (%d: %s)\n", errnum, strerror(errnum));
            }
            else
                printf("read OK: %d bytes (%s)\n", (int)n, buffer);
            close(fd);
        }
        return(0);
    }
    

    【讨论】:

    • 我在网上看过那本书,名字旁边写着“2.nd edition”,我还没有纸质版所以我不知道
    • 有趣 - 你在看的东西使用原型吗?如果是这样,它是第 2 个 Edn 而不是第 1 个。但是,在我的第一版 (p170) 副本中,有“#define DIRSIZ 14 / struct direct { ino_t d_ino; char d_name[DIRSIZ]; };”(没有提及opendir() 等)。在我在 p180 上的第二版 Edn(标记为“基于提议的 ANSI C 草案”,日期为 1988 年,第一次印刷)的副本中,有“#define NAME_MAX 14 / typedef struct { long ino; char name[NAME_MAX+1]; } Dirent;”(以及对opendir() 等人的讨论。您的代码看起来更接近对我来说,第一版比第二版 - 因此我的评论。
    • @paleman:那就是 K&R 的第 2 版。您是否更多地关注“C 答案书”(Tondo 和 Gimpel - amazon.com/C-Answer-Book-Clovis-Tondo/dp/0131098772)?如果是这样,那么它可能包含您展示的内容 - 我没有副本可供查看。你有可以分享的在线网址吗?
    • 我刚看了,两者都有。"#define NAME_MAX 14 / typedef struct { long ino; char name[NAME_MAX+1]; } Dirent;"将是可移植结构,它有注释 /* 可移植结构条目 */,它还有“#define DIRSIZ 14 / struct direct { ino_t d_ino; char d_name[DIRSIZ]; };”这将是该特定系统的目录条目。在示例中,作者还编写了 opendir、readdir 和 closedir。只有他们的 readdir 返回 'Dirent *' 而不是 'struct dirent *'。在 readdir 的主体中,它们将信息从“struct direct”复制到“static Dirent”并返回地址 od“Dirent”。
    • 我没有也没有读过“The C Answer Book”。我知道的唯一在线 URL 已经不存在了,他们决定把它拿走,可能是因为版权,对不起。
    【解决方案4】:

    boost::filesystem::directory_iterator 提供 Windows FindFirstFile/FindNextFile API 和 POSIX readdir_r() API 的可移植等效项。见this tutorial

    请注意,这是 C++ 而不是纯 C。

    【讨论】:

      猜你喜欢
      • 2012-11-25
      • 2019-02-16
      • 2012-06-25
      • 2011-02-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多