我正在研究一种评估来自USB激光扫描仪数据的C应用程序,该激光扫描仪充当串行设备。出于测试目的,我还允许从文件中读取测试数据,因为始终连接扫描仪并不方便。
我像这样打开文件/设备:
FILE *fp = fopen(argv[1], "a+b");
根据我是否要从文件或设备中读取,我会传递文件路径或类似/dev/cu.usbmodemfd121
(我在Mac上)。
只要我之前已经初始化了激光扫描仪,这种方法就可以正常工作,但我宁愿让我的应用程序这样做。但是,为了做到这一点,我必须首先弄清楚我是否正在从文件或设备中读取数据。 考虑到FILE *
返回的fopen
,我该怎么做?
我尝试使用fseek(fp, 1, SEEK_END)
我希望扫描仪失败,因为它的流没有"结束"但是对于某些原因fseek
不会失败..
答案 0 :(得分:6)
您可以使用fileno
获取文件描述符,然后对其执行fstat
。它填充的struct stat
包含类似st_mode
的内容,它显示了fd的类型。我猜你的非文件设备S_ISCHR
将是真的,或者至少S_ISREG
将是假的。
如果您可以控制它,请不要执行fopen
。直接使用open
获取文件描述符,如果您真的需要C流,请使用fdopen
。
答案 1 :(得分: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;
}