【问题标题】:How to get the file length in C on Linux?如何在 Linux 上用 C 语言获取文件长度?
【发布时间】:2018-10-11 15:36:25
【问题描述】:

我正在寻找相当于微软在 Linux 中的_filelength。我试过了,但它不正确。

long _filelength(char *f)
{
    struct stat st;
    stat(f, &st);
    return st.st_size;
}

if((hfile = fopen("data.arp","rb"))!=NULL)
    fsize = _filelength(fileno(hfile));

如何在 Linux 上用 C 语言获取文件长度?

【问题讨论】:

标签: linux file io filesize


【解决方案1】:

我正在寻找 _filelength 在 linux 中的等价物。

这是一种非常错误的方法,显示了错误的心态。 在 Linux 上没有完全等同于 Windows 的 _filelength。 Linux 不是 Windows,Windows 也不是 Linux。每个操作系统都有自己的API 和自己的文件愿景(在 Linux 上,它们是 inode,请参阅 inode(7)this 答案...)、进程等... Linux 大多兼容 POSIX,所以学习 POSIX 并阅读一些关于 Linux 系统编程的书,也许是旧的 ALP 或更新的东西。不要期望(甚至不要尝试)在 Linux 上找到每个 Windows 或 WinAPI 函数的等效项。见intro(2)syscalls(2)intro(3)

请仔细阅读stat(2)。它需要一个字符串(某个文件路径),而不是file descriptor(就像fstat 那样),就像fileno(3) 给出的那样。它可能会失败(您需要了解原因,可能使用errno(3),这绝不是负面的)。

顺便说一句,名称以_ 开头的标识符是保留的。

也许你可以试试:

long filelength(const char*filpath) { // don't use that. Learn POSIX API
   struct stat st;
   if (stat(filpath, &st)) /*failure*/
      return -1; // when file does not exist or is not accessible
   return (long) st.st_size;
}

但实际上你最好直接在你的程序中使用stat(并且检查errno(3)是否失败,而不是像我上面那样简单地返回-1),你可能应该使用stat返回的other元数据。

Linux(和 Unix)也有 sparse fileshard linksdevice filessymbolic links、匿名文件(例如仍然打开的 inode,但文件系统中不再存在)、fifo(7)-s、 unix(7) 套接字等......您可能需要处理它们(但它们在 Windows 上没有完全相同的等效项)。

另请阅读Operating Systems: Three Easy Pieces

您可以使用多平台框架,例如 PocoBoostQt。他们试图在几个操作系统之上提供一些常见的abstraction(但一些细节仍然很重要,很难隐藏或抽象;例如文件path在Windows和Linux上是不一样的。见path_resolution(7) ...)

您应该使用所有警告和调试信息进行编译(所以gcc -Wall -Wextra -gGCC)。然后use the gdb debugger。您也可以使用strace(1) 来了解您的程序所做的system calls

【讨论】:

  • 是的。你检查了errno 吗?正如我试图解释的那样,你有错误的方法。改变你的心态,让你对 Linux 友好。不要用 WinAPI 术语思考。学POSIX API,不一样!
  • 我绝对同意学习 Linux API。我不确定我是否同意使用它们。如果您正在编写适用于 Windows 和 Linux 的代码,您可能需要一个可移植层,并且您可能会认为您的可移植层看起来更像 winapi 而不是 Linux。
  • errno 永远不会是 -1。你有什么问题。在您的问题中显示一些 minimal reproducible example
  • 精彩介绍。
【解决方案2】:
FILE *fp = fopen("filename", "rb");
fseek(fp, 0, SEEK_END);
int lengthOfFile = ftell(fp);
fclose(fp);

【讨论】:

    【解决方案3】:

    也许你可以试试这个。

    size_t _filelength(int filedes)
    {
        off_t pos = lseek(filedes, 0, SEEK_CUR);
        if (pos != (off_t)-1)
        {
            off_t size = lseek(filedes, 0, SEEK_END);
            lseek(filedes, pos, SEEK_SET);
            return (size_t)size;
        }
        return (off_t)-1;
    }
    

    【讨论】:

      【解决方案4】:

      你必须在文件中寻找。

      fseek(file, 0L, SEEK_END);
      

      然后获取当前位置:

      fileSize = ftell(file);
      

      然后将位置重置回开始使用:

      rewind(file);
      
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-12-01
      • 2014-12-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-09-17
      相关资源
      最近更新 更多