【问题标题】:Determine if FILE * is writable确定 FILE * 是否可写
【发布时间】:2013-08-31 02:14:33
【问题描述】:

有没有办法判断FILE * 是在什么模式下打开的?

具体来说,我需要判断文件流是否可写。要么只是它是否可写的真/假结果,要么模式本身的const char * 是好的。

【问题讨论】:

  • 没有标准的做法,但大多数平台都会让你以某种方式去做。如果您不希望完全跨平台(或者不介意针对不同平台使用不同的代码),您应该指定您的操作系统,您可能会得到一个不错的答案。

标签: c file


【解决方案1】:

不直接回答你的问题,但你可以使用freopen

FILE *freopen(const char *path, const char *mode, FILE *stream);

它在指定流上打开指定文件,如果流已经存在则先关闭该流 打开。如果流之前有一个方向,freopen 会清除它。

【讨论】:

    【解决方案2】:

    是的,有一些方法,但它们本质上是历史性的,并且被其他人不赞成。此外,您将需要研究/测试确切的值是什么,然后冒着新版本的操作系统会推翻您的假设的风险。

    无论如何,鉴于此警告,您可以测试 FILE 结构内的字段以获取特定值。该结构在 stdio.h 中,感兴趣的字段是:_flag 和 _file。

    编写一些特征代码并在您的系统上运行,如:

    #include <stdio.h>
    
    main()
    {
        FILE *fp;
    
        fp = fopen("test1.txt", "r");
        printf("(r) _flag = %04x, _file = %04x\n", fp->_flag, fp->_file);
    
        fp = fopen("test2.txt", "a");
        printf("(a) _flag = %04x, _file = %04x\n", fp->_flag, fp->_file);
    
        fp = fopen("test3.txt", "w");
        printf("(w) _flag = %04x, _file = %04x\n", fp->_flag, fp->_file);
    
    }
    

    您可以看到与每种打开类型关联的 _flag 值。

    在 Windows/XP 上,我得到了以下信息:

    (r) _flag = 0001, _file = 0003
    (a) _flag = 0002, _file = 0004
    (w) _flag = 0002, _file = 0005
    

    注意,追加与写入相同! _file 值似乎是 _iob 的索引,其中标准输入为 _file = 0000。

    不管怎样,乱来,实验一下。尝试从文件中写入/读取数据,看看 _flag 是否改变???

    【讨论】:

    • 这是基于任何标准,还是仅基于 Windows?
    • 它的起源早于 K&R,第二版。据我了解,Unix 保留了 FILE 结构的更缩写版本。但是您应该能够在 stdio.h 中找到并查看 FILE 是否包含 Unix 中的 _flag 或 _mode 字段。我使用的是 Windows/XP 并且可以获得该信息。
    • 任何实现都有这样的东西,所以说它的起源早于标准是一个空洞的事实。 K&R 第二版本质上是对 C90 标准 IIRC 的评论,而不是标准化或创新的尝试。 Unix 既不是标准也不是操作系统。这个答案只不过是建议对您所在的任何平台进行逆向工程,这不是一个好建议。
    • @Potatoswatter 这不适用于 glibc:它将 FILE 类型声明为真正的不透明类型; stdio.h 所说的只是有一些struct _IO_FILE,但没有定义。所以,应该说,如果你能找到一种方法,这就是 100% 的黑客攻击。
    • @cmaster,相反,为 Windows 编写的代码(我知道这是可能的)不能直接移植到 *nix(我必须弄清楚要做)。注意,要确定 _IO_FILE 的格式,请编写如下代码:printf("%0xf", *((char *) fp)); 然后 fp+4 等,然后解开谜题。
    【解决方案3】:

    一般来说,没有没有。您需要自己跟踪这些信息。您也许可以尝试写入文件并获得错误或成功,但这取决于您要执行的操作。

    【讨论】:

      【解决方案4】:
      FILE * f;
      //...
      if (f->flags == 2 || f->flags == 3) {
           // writable
      }
      

      【讨论】:

        猜你喜欢
        • 2011-01-07
        • 2014-01-08
        • 2012-04-11
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-03-16
        • 2018-08-03
        相关资源
        最近更新 更多