引言

  有一天看见看到返回文件长度代码返回值都是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. Java的第一个程序-Hello, World !

    学了一个月的Java,现在总结一下,就算复习了. 一.安装Java环境 这个没啥好说的. 1. 官网下载JDK安装 2. 配置环境变量.注意的是:环境变量配置好以后,如果cmd中运行 java 命令没 ...

  2. [BZOJ4822] [CQOI2017] 老C的任务

    题目链接 BZOJ:https://lydsy.com/JudgeOnline/problem.php?id=4822. 洛谷:https://www.luogu.org/problemnew/sho ...

  3. [洛谷P3346][ZJOI2015]诸神眷顾的幻想乡

    题目大意:给你一棵$n$个点的树,最多有$20$个叶子节点,问共有几个不同的子串 题解:广义$SAM$,对每个叶子节点深搜一次,每个节点的$lst$设为这个节点当时的父亲,这样就可以时建出来的$SAM ...

  4. 洛谷 P1363 幻想迷宫 解题报告

    P1363 幻想迷宫 题目描述 背景 Background (喵星人LHX和WD同心协力击退了汪星人的入侵,不幸的是,汪星人撤退之前给它们制造了一片幻象迷宫.) WD:呜呜,肿么办啊-- LHX:mo ...

  5. js空对象判断 isPlainObject

    //有缺陷,JSON.stringify(obj)中,如果obj本来是空的,又继承了一个非空的对象那么结果也会是“{}” 1. JSON.stringify(obj) == '{}' 2. Objec ...

  6. bzoj2058: [Usaco2010 Nov]Cow Photographs(逆序对)

    题目大意:给出n个数的序列,每次可以交换相邻的两个数,问把序列变成编号i在编号i+1左边,编号1在编号n右边(一个环)最少需要多少步.如:35421最少交换两次变为34512. 一开始看到这题,只会O ...

  7. IDEA的使用总结篇-1

    随笔:随着回首所在的公司的日益扩大,所在的技术中心也日渐兵强马壮,但由于各位新老同仁的开发工具一直未曾统一,所以小编的老大终于一声令下,统一开发工具!统一使用IDEA,而且每个人今天要交一份IDEA的 ...

  8. 使用rsyslog编程,产生trace信息,记录到日志中

    参考:http://blog.csdn.net/nowayings/article/details/38926501 https://www.cnblogs.com/bonelee/p/6234647 ...

  9. Django Session配置

    Django Session的三种存储方式 SESSION_ENGINE='django.contrib.sessions.backends.db' # default 保存到数据库中,依赖 'dja ...

  10. BZOJ1878: [SDOI2009]HH的项链 (离线查询+树状数组)

    1878: [SDOI2009]HH的项链 题目链接:https://www.lydsy.com/JudgeOnline/problem.php?id=1878 Description: HH有一串由 ...