引言

  有一天看见看到返回文件长度代码返回值都是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 0;

    fseek(txt, 0, 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 = 1;

    while (i < argc) {
        path = argv[i];
        printf("%s => %ld\n", path, file_getsize(path));
        ++i;
    }

    return 0;
}



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

java根据报文长度读取内容 java读取文件长度_linux

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

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

 

前言

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

java根据报文长度读取内容 java读取文件长度_linux_02

测试结果如下

java根据报文长度读取内容 java读取文件长度_文件路径_03

这时候我们需要用新的文件操作代码,想办法了. 其实上面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 = 1;

    while (i < argc) {
        path = argv[i];
        printf("%s => %ld\n", path, file_getsize(path));
        ++i;
    }

    return 0;
}

/*
 * 得到文件长度, windows 上适用方法
 * path        : 文件路径
 *            : 返回文件长度
 */
int64_t
file_getsize(const char * path) {
    struct _stat64 info = { 0 };

    if (!path || !*path)
        return 0;

    _stat64(path, &info);
    return info.st_size;
}


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

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

java根据报文长度读取内容 java读取文件长度_java根据报文长度读取内容_04

到这里我们. 在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 = 1;

    // 测试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 0;
}

/*
 * 得到文件长度, linux 上适用方法
 * path        : 文件路径
 *            : 返回文件长度
 */
int64_t
file_getsize(const char * path) {
    struct stat info = { 0 };

    if (!path || !*path)
        return 0;

    stat(path, &info);
    return info.st_size;
}


 编译命令



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



 后面查看 sys/stat.c 源码

java根据报文长度读取内容 java读取文件长度_java根据报文长度读取内容_05

 

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

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

java根据报文长度读取内容 java读取文件长度_文件路径_06

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

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


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