【问题标题】:How to detect if a C filestream points to a file or a serial device?如何检测 C 文件流是否指向文件或串行设备?
【发布时间】:2014-03-21 18:32:50
【问题描述】:

我正在开发一个 C 应用程序,用于评估来自 USB 激光扫描仪的数据,该扫描仪充当串行设备。出于测试目的,我还允许从文件中读取测试数据,因为始终连接扫描仪并不方便。

我这样打开文件/设备:

FILE *fp = fopen(argv[1], "a+b");

根据我是要从文件还是设备中读取,我会传递一个文件路径或类似 /dev/cu.usbmodemfd121 的东西(我在 Mac 上)。

只要我之前初始化了激光扫描仪,它就可以正常工作,但我宁愿让我的应用程序这样做。但是,为了做到这一点,我必须首先弄清楚我是从文件还是设备中读取。 鉴于fopen 返回的FILE *,我该怎么做?

我尝试使用fseek(fp, 1, SEEK_END),我预计扫描仪会失败,因为它的流没有“结束”,但由于某些原因fseek 不会失败..

【问题讨论】:

  • 明显的人说,“如果文件名以/dev 开头,你不能只检查文件名并假设你正在与设备通话吗?”
  • Obvious Man 非常务实,虽然我更喜欢 @cnicutars,因为它更通用,如果他发布了它,我会赞成 Obvious Man 的答案。

标签: c unix file-io


【解决方案1】:

您可以使用fileno 获取文件描述符,然后对其执行fstat。它填充的struct stat 包含类似于st_mode 的想法,它显示了fd 的类型。我猜你的非文件设备S_ISCHR 会是真的,或者至少S_ISREG 会是假的。


如果您可以控制它,请不要使用fopen。直接使用open获取文件描述符,如果你真的想要C流,则使用fdopen。

【讨论】:

  • 先使用open后使用fdopen与先使用fopen后使用fileno和fstat相比有什么优势?
  • @x3ro 我想这两种方式都没有太大的优势,你是对的。
【解决方案2】:

@cnicutar 的解决方案效果很好。这是我最终得到的结果,以防它对某人有所帮助(为清楚起见,删除了错误检查):

#include <fcntl.h> /* open syscall */
#include <sys/stat.h>

int fd = -1;
int status;
FILE *fp = NULL;
struct stat fd_stat;
bool serial_device = false;

fd = open("/foo/bar/baz", O_RDONLY);
fp = fdopen(fd, "rb");
status = fstat(fd, &fd_stat);

printf("S_ISCHR: %d\n", S_ISCHR(fd_stat.st_mode));
printf("S_ISREG %d\n", S_ISREG(fd_stat.st_mode));

if(!S_ISREG(fd_stat.st_mode)) {
    serial_device = true;
}

【讨论】:

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