【问题标题】:C open() function fails. Are my parameters wrong?C open() 函数失败。我的参数错了吗?
【发布时间】:2017-10-30 19:17:42
【问题描述】:

此函数无法打开文件。我的参数是否错误或可能导致此问题的原因?

    int CreateFile(const char *filename){
        char filepath[strlen(filename) + 3];
        sprintf(filepath, "./%s", filename);
        int fd = open(filepath, O_CREAT, O_APPEND, S_IWGRP);
        if(fd == -1) printf("file read failed\n");
        return fd;
    }

Xcode 仅将“文件读取失败”打印到控制台。我也尝试通过终端运行它,但这也无济于事。

我修复了 NetMage 指出的一个问题:

int CreateFile(const char *filename){
    char filepath[strlen(filename) + 3];
    sprintf(filepath, "./%s", filename);
    int fd = open(filepath, O_CREAT|O_APPEND, S_IWGRP);
    if(fd == -1) printf("file read failed\n");
    return fd;
}

不幸的是,这并没有解决问题

【问题讨论】:

  • 明确一点,您知道它无法打开是因为它正在打印"file read failed\n",对吧?
  • 是的,刚刚编辑了。
  • 您没有打开文件进行阅读,因此错误消息有点误导......
  • 没错,我把那行放在那里并没有想太多,只是想看看它是否被打印出来。对不起
  • perror(filepath)(如果在open 失败之后立即调用,因此没有其他函数有机会更改errno)会告诉您调用失败的原因。

标签: c file posix


【解决方案1】:

第 1 步 - 验证 filepath 的设置是否正确,方法是将其打印到终端或在调试器中检查。

第 2 步 - 验证文件是否存在在该路径中,并且已设置其权限以便您可以打开它。如果filepath"./foo",那么一个名为foo 的文件最好存在于当前工作目录(您运行程序的目录)中,并且至少需要读取它权限。

第 3 步 - 如果文件不存在,请验证您是否有权在当前工作目录中创建新文件。

第 4 步 - 如果在完成所有这些操作后仍然出现错误,请检查 errno。除了“它不起作用”之外,它还会为您提供一些额外的信息。

#include <errno.h>
...
if(fd == -1) 
{
  switch( errno )
  {
    case EACCESS: // permission issues
      handle_permission_issue();
      break;

    case EEXIST: // file already exists and you used O_CREAT and O_EXCL
      handle_already_exists_issue();
      break;

    case EFAULT: // bad path
      handle_bad_path_issue()
      break;

    ...
  }
  printf("file read failed\n");
}

NetMage 指出了一个问题 - 您的标志需要按位或运算在一起,而不是作为单独的参数列出。很惊讶编译器没有为此对你大喊大叫。

【讨论】:

  • 如果一个新文件不存在,O_CREAT 标志是否应该创建一个新文件?如何检查我创建新文件的权限?可以在程序中设置权限吗?
  • @FrostyWhite:它应该如果你有权限这样做在当前目录中。由于您提到了 XCode,我假设您使用的是 Mac,因此打开一个终端窗口,导航到您正在运行该程序的目录,然后输入 ls -lad $(pwd)。最左边的列将显示该目录的权限;它应该类似于drwxr-xr-x。这表明该目录的所有者拥有读、写和执行权限,而其他人只有读和执行权限。
  • @FrostyWhite:不过,在开始讨论之前,请在尝试打开后检查errno 的值——这可能是其他问题。
【解决方案2】:

open 函数只接受oflags 的一个参数,必须一起进行位或运算:

#include <errno.h>
#include <string.h>

int fd = open(filepath, O_CREAT|O_APPEND, S_IWGRP);
if (fd == -1) printf("file read failed: %s\n", strerror(errno));

【讨论】:

  • 那么我建议打印/显示errno,这样你就知道发生的错误,这很可能是你没有权限写入当前目录。
  • 对不起,我对所有这些更高级的东西都是新手,那是怎么做的?
  • fd-1 时,我添加了更多代码以输出errno
【解决方案3】:

根据the POSIX documentation for open()(稍微重新格式化,并注意粗体文本):

概要

#include <sys/stat.h> #include <fcntl.h>

int open(const char *path, int oflag, ...);

...

oflag 的值由标志位的按位或构成 从以下列表中,定义在 . 应用程序应 准确指定前五个值之一(文件访问模式) 低于oflag的值:

  • O_EXEC 仅打开执行(非目录文件)。如果将此标志应用于目录,则结果未指定。
  • O_RDONLY 仅供阅读。
  • O_RDWR 开放阅读和写作。如果将此标志应用于 FIFO,则结果未定义。
  • O_SEARCH 打开目录仅用于搜索。如果将此标志应用于非目录文件,则结果未指定。
  • O_WRONLY 仅供写作。

...

您需要至少包含这五个标志中的一个,例如:

int fd = open(filepath, O_WRONLY|O_CREAT|O_APPEND, S_IWGRP);

请注意,其他故障仍可能发生。如 cmets 中所述,您将 "./" 添加到文件名前,这可能会导致问题,例如,如果您通过 "/tmp/filename" 并且当前工作目录中不存在 tmp 目录,如open() 不会在任何路径中创建缺失的目录。

【讨论】:

    猜你喜欢
    • 2016-09-29
    • 2016-02-24
    • 2016-08-05
    • 2020-08-01
    • 2013-09-19
    • 1970-01-01
    • 2021-07-01
    • 2011-01-21
    • 1970-01-01
    相关资源
    最近更新 更多