【问题标题】:fseek fails on open file pointerfseek 在打开文件指针上失败
【发布时间】:2014-11-19 05:55:57
【问题描述】:

我在使用 fseek 时遇到问题。我有一个包含获取的 HTTP 数据的文件指针。然后我让 libmagic 确定文件的 mime 类型,然后想倒带:

char *mime_type (int fd)
{
    char *mime;
    magic_t magic;

    magic = magic_open(MAGIC_MIME_TYPE);
    magic_load(magic, MAGIC_FILE_NAME);
    mime = (char*)magic_descriptor(magic, fd);

    magic_close(magic);
    return (mime);
}

int fetch_pull() {
    fetch_state = fopen("/tmp/curl_0", "r");
    if (fetch_state == NULL) {
      perror("fetch_pull(): Could not open file handle");
      return (1);
    }
    fd = fileno(fetch_state);
    mime = mime_type(fd);
    if (fseek(fetch_state, 0L, SEEK_SET) != 0) {
      perror("fetch_pull(): Could not rewind file handle");
      return (1);
    }
    if (mime != NULL && strstr(mime, "text/") != NULL) {
      /* do things */
    } else if (mime != NULL && strstr(mime, "image/") != NULL) {
      /* do other things */
    }
    return (0);
}

这会抛出“fetch_pull():无法回退文件句柄:错误的文件描述符”。怎么了?

【问题讨论】:

    标签: c file fseek libmagic


    【解决方案1】:

    /tmp/curl_0 是一个管道,不是吗?您不能倒带管道。读过的都没有了。

    而且你不能将 FILE 操作和文件描述符操作结合起来,因为 FILE 有一个额外的缓冲区,它们会提前读取。

    如果/tmp/curl_0regular file,则使用open(const char *path, int oflag, ...) 打开文件描述符。调用mime_type(fd) 后,您可以先倒带流,然后将文件描述符包装到带有fdopen(int fildes, const char *mode) 的FILE 句柄中。或者只是关闭文件描述符,然后使用常规的fopen()

    int fd = open("/tmp/curl_0", O_RDONLY);
    if (fd == -1) {
        perror("Could not open file");
        return -1;
    }
    char *mime = mime_type(fd);
    
        /***** EITHER: */
    
    close(fd);
    FILE *file = fopen("/tmp/curl_0", "r");
    
        /***** OR (the worse option!) */
    
    if (lseek(fd, 0, SEEK_SET) == -1) {
        perror("Could not seek");
        return -1;
    }
    FILE *fdopen = fopen(fd, "r");
    
        /***********/
    
    if (!file) {
        perror("Could not open file");
        return -1;
    }
    /* do things */
    fclose(file);
    

    【讨论】:

    • /tmp/curl_0 是一个文件。好像我误解了文件描述符。我认为文件描述符只是操作系统对文件流的整数表示。我错了吗?
    • 文件描述符是文件流的句柄。 FILE 对象为各种流添加缓冲区和抽象。您可以使用fdopen() 来包装描述符,但您永远不会发现需要使用fileno()
    • 为什么第二种方式比第一种差?
    • 因为这是一个不必要的微优化。更难理解(→ 可维护性),最多也快几纳秒,因为操作系统按原样高效地缓存文件元数据。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-03-06
    • 2011-07-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-02-04
    • 2020-09-12
    相关资源
    最近更新 更多