引言

  有一天看见看到返回文件长度代码返回值都是long,就感觉怪怪的, 一般32位long最大也就2G.

而大文件太多了, 一个Dota2安装包估计都得10多G吧. 一般C得到文件长度代码

/*
* 得到文件长度, 一种通用老的写法
* path : 文件路径
* : 返回文件长度
*/
long
file_getsize(const char * path) {
FILE * txt;
long rt; if ((!path) || !(txt = fopen(path, "rb")))
return ; fseek(txt, , SEEK_END);
rt = ftell(txt); fclose(txt);
return rt;
}

如上套路, 比较耿直的. 写个测试代码

#include <stdio.h>

/*
* 得到文件长度, 一种通用老的写法
* path : 文件路径
* : 返回文件长度
*/
long file_getsize(const char * path); int main(int argc, char * argv[]) {
const char * path;
int i = ; while (i < argc) {
path = argv[i];
printf("%s => %ld\n", path, file_getsize(path));
++i;
} return ;
}

执行正常的测试结果看下图

扯一点, 对于 fopen "rb"后面b表示采用二进制流方式处理, 默认是t文本模式. 前者速度快一点, 后者做了一些特殊处理.

主要是不同系统对换行符处理不同业务诞生的. 推荐用 b 二进制处理方式更快些.(21世纪是个装b的年代, 全是BBB)

前言

  这里我们再做一个实验 , 看下面大文件 . 继续用上面代码测试一下. 先看测试文件

测试结果如下

这时候我们需要用新的文件操作代码,想办法了. 其实上面ftell方式得到代码, 来回移动文件指针性能很低.

因为文件大小操作系统知道, 直接问它要是最快的. 先在window 上写一段代码

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <inttypes.h> /*
* 得到文件长度, windows 品台用法
* path : 文件路径
* : 返回文件长度
*/
int64_t file_getsize(const char * path); int main(int argc, char * argv[]) {
const char * path;
int i = ; while (i < argc) {
path = argv[i];
printf("%s => %ld\n", path, file_getsize(path));
++i;
} return ;
} /*
* 得到文件长度, windows 上适用方法
* path : 文件路径
* : 返回文件长度
*/
int64_t
file_getsize(const char * path) {
struct _stat64 info = { }; if (!path || !*path)
return ; _stat64(path, &info);
return info.st_size;
}

上面就是完整的测试代码, 主要通过 sys/stat.h 下面_stat64 函数得到 8字节长度的文件大小表示.

我们也继续测试一下.  结果很满意

到这里我们. 在window上测试完毕.

正文

  我们在linux上测试一下. 先看代码我写好的代码 main_linux.c

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <inttypes.h> /*
* 得到文件长度, linuxs 平台用法
* path : 文件路径
* : 返回文件长度
*/
int64_t file_getsize(const char * path); int main(int argc, char * argv[]) {
const char * path;
int i = ; // 测试demo
struct stat info;
printf("info.st_size size = %ld\n", sizeof(info.st_size));
printf("unsigned long size = %ld\n", sizeof(unsigned long)); while (i < argc) {
path = argv[i];
printf("%s => %ld\n", path, file_getsize(path));
++i;
} return ;
} /*
* 得到文件长度, linux 上适用方法
* path : 文件路径
* : 返回文件长度
*/
int64_t
file_getsize(const char * path) {
struct stat info = { }; if (!path || !*path)
return ; stat(path, &info);
return info.st_size;
}

编译命令

gcc -Wall -ggdb2 -o main_linux.out main_linux.c

后面查看 sys/stat.c 源码

有兴趣可以看看, 得到的结论是, linux会根据平台自动帮我们确定是 stat64 还是 stat. 我用的是64位的, 默认stat也是stat64.

返回的long 是 8字节. 可以看下面结果

这里也解决了一个问题, 一般 off_t 结构是8字节的unsigned long 结构. window是long long结构. 不同平台实现不一样.

如果希望这个函数是跨平台的 那么 需要在 window 上做

#if defined(_MSC_VER)
#  define stat _stat64
#endif

是不是很简单. 就能够让我们的得到文件长度代码跨平台了. 哎, 这种语言, 细节太多, 不利于生产. 大师们也老了, 改进的机会也少了, 太稳定了.

如果只为了快速的性能那么没有谁比C更适合的了, 更快速轻巧的了.  一切都是抉择, 没有最好, 只有最合适.

后记

  错误是难免的, 欢迎交流提高.  也许我们年少的时候幻想着成为大英雄, 最终也只是拿着血汗钱成了房奴.

  

有梦想的人是令人羡慕的, 有梦想的人是令人惋惜的.  爱我所爱, 开心就好 ~~~~~~~~~

  

C基础 如何得到文件长度的更多相关文章

  1. Java基础之读文件——使用通道读取混合数据1(ReadPrimesMixedData)

    控制台程序,本例读取Java基础之写文件部分(PrimesToFile2)写入的Primes.txt. 方法一:可以在第一个读操作中读取字符串的长度,然后再将字符串和二进制素数值读入到文本中.这种方式 ...

  2. ComicEnhancerPro 系列教程十八:JPG文件长度与质量

    作者:马健邮箱:stronghorse_mj@hotmail.com 主页:http://www.comicer.com/stronghorse/ 发布:2017.07.23 教程十八:JPG文件长度 ...

  3. Java基础之读文件——使用通道读取混合数据2(ReadPrimesMixedData2)

    控制台程序,本例读取Java基础之写文件部分(PrimesToFile2)写入的Primes.txt. 方法二:设置一个任意容量的.大小合适的字节缓冲区并且使用来自文件的字节进行填充.然后整理出缓冲区 ...

  4. Java基础之读文件——使用通道读二进制数据(ReadPrimes)

    控制台程序,本例读取Java基础之写文件部分(PrimesToFile)写入的primes.bin. import java.nio.file.*; import java.nio.*; import ...

  5. Java基础之读文件——从文件中读取文本(ReadAString)

    控制台程序,使用通道从缓冲区获取数据,读取Java基础之写文件(BufferStateTrace)写入的charData.txt import java.nio.file.*; import java ...

  6. Java基础之读文件——使用缓冲读取器读取文件(ReaderInputFromFile)

    控制台程序,本例读取Java基础之写文件部分(WriterOutputToFile)写入的Saying.txt. import java.io.*; import java.nio.file.*; i ...

  7. Java基础之读文件——使用输入流读取二进制文件(StreamInputFromFile)

    控制台程序,读取Java基础之读文件部分(StreamOutputToFile)写入的50个fibonacci数字. import java.nio.file.*; import java.nio.* ...

  8. UNIX,基础知识,文件IO,文件和目录

    2015.1.27星期二,早晨阴天,中午下雪了今天上午老师不上课,程序语句,记一下:main(void){ int c; while((c = getc(stdin)) != EOF) if(putc ...

  9. vc++基础班[21]---文件的基本操作之CFile

    ①.文件的创建.打开.关闭: 文件的创建.打开:CFile::Open 文件的关闭:CFile::Close   CFile::modeCreate:以新建方式打开,如果文件不存在,则新建:如果文件已 ...

随机推荐

  1. Go语言【第十一篇】:Go数据结构之:结构体

    Go语言结构体 Go语言中数组可以存储同一类型的数据,但在结构体中我们可以为不同项定义不同的数据类型,结构体是由一系列具有相同类型或不同类型数据构成的集合.结构体表示一项记录,比如:保存图书馆的书籍记 ...

  2. openstack中间件message queue 与memcached环境部署

    为什么要安装中间件 组件间的通信使用的是REST API 而组件内部之间的通信则是使用的中间件 首先登陆openstack的官网查看官方文档 www.openstack.org 应为在部署一个架构之前 ...

  3. [洛谷P4900]食堂

    题目大意:$n(n\leqslant10^6)$组询问,每组询问给出$l,r(l,r\leqslant10^6)$,求($\{\dfrac ij\}$表示$\dfrac ij$的小数部分): $$\s ...

  4. BZOJ5285 & 洛谷4424 & UOJ384:[HNOI/AHOI2018]寻宝游戏——题解

    https://www.lydsy.com/JudgeOnline/problem.php?id=5285 https://www.luogu.org/problemnew/show/P4424 ht ...

  5. 无序数组中第Kth大的数

    题目:找出无序数组中第Kth大的数,如{63,45,33,21},第2大的数45. 输入: 第一行输入无序数组,第二行输入K值. 该是内推滴滴打车时(2017.8.26)的第二题,也是<剑指of ...

  6. Navcat中Oracle连接的坑-Instant Client

    报错信息: 官方下载Instant Client下载: http://www.oracle.com/technetwork/cn/topics/intel-macsoft-102027-zhs.htm ...

  7. LoadRunner中的IP欺骗

    应用程序服务器和网络设备使用IP地址来识别客户端.应用程序服务器通常会对来自同一计算机的客户端信息进行高速缓存. 网络路由器尝试对原信息和目标信息进行高速缓存以优化吞吐量.如果多个用户具有相同的IP地 ...

  8. 二叉树中和为某一值得路径 java实现

    本题来自<剑指offer> 路径为从根节点到叶节点一条路径,路径经过的各节点数值之和等于某一给定数值,则打印路径上的节点 因为需要打印满足条件的路径节点信息和各节点之和,需要栈记录经过的节 ...

  9. stout代码分析之五:UUID类

    UUID全称通用唯一识别码,被广泛应用于分布式系统中,让所有的元素具有唯一的标识. stout中UUID类继承自boost::uuids::uuid.api如下: random, 产生一个UUID对象 ...

  10. webpack插件url-loader使用规范

    其实说到性能优化,他的范围太广了,今天我们就只聊一聊通过webpack配置减少http请求数量这个点吧. 简单说下工作中遇到的问题吧,我们做的一个项目中首页用了十多张图片,每张图片都是一个静态资源,所 ...