技术问题库

1. 文件管理

1.1 ftell fread接口Windows下表现异常

  • 问题背景:采用 fopen 类接口编写了一段文件内容解析代码,其中会采用 ftell、fseek 获取和修改文件偏移地址;Linux环境代码运行没问题,但到了 Windows环境下ftell接口返回有一处出错,但换个文件又不会出错了,具有偶发性。

  • 知识点:Windows下编辑器文本文件默认采用CRLF换行符,Linux下默认为LF换行符。本文测试的文本文件采用CRLF换行,0x0d 0x0a

  • 测试代码

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    #include <stdint.h>
    #include <stdio.h>

    int main(int argc, char **argv)
    {
    char *file_name = argv[1];

    FILE *fp = fopen(file_name,"r");
    if (fp == NULL) {
    return -1;
    }

    uint8_t bufz[16];
    while (!feof(fp)) {
    int ret = fread(bufz,1,sizeof(bufz),fp);
    printf("current offset: %ld, ",ftell(fp));
    printf("ret:%d [",ret);
    for (int i = 0; i < ret; i++) {
    printf("%02x ",bufz[i]);
    }
    printf("]\n");
    }

    fclose(fp);

    return 0;
    }
  • 测试结果

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    // 文件内容的二进制显示
    00000000 54 68 69 73 20 69 73 20 61 20 41 6c 69 6e 65 0d |This is a Aline.|
    00000010 0a 54 68 69 73 20 69 73 20 61 20 42 6c 69 6e 65 |.This is a Bline|
    00000020

    // Windows fopen("r")
    current offset: 0
    current offset: 17, ret:16 [54 68 69 73 20 69 73 20 61 20 41 6c 69 6e 65 0a ]
    current offset: 32, ret:15 [54 68 69 73 20 69 73 20 61 20 42 6c 69 6e 65 ]

    // Linux
    current offset: 16, ret:16 [54 68 69 73 20 69 73 20 61 20 41 6c 69 6e 65 0d ]
    current offset: 32, ret:16 [0a 54 68 69 73 20 69 73 20 61 20 42 6c 69 6e 65 ]
    current offset: 32, ret:0 []
    1. 对于Windows下,fread 接口读取文件遇到 \r(0x0d)认为是换行符,0x0d不返回到用户,然后继续读取满16字节返回;
    2. 对于Linux下,fread 接口没有Linux下这种骚操作,一切正常。
  • 问题解决

    以二进制形式打开文件操作,便可解决问题!fopen(file_name,”rb”);

    1
    2
    3
    4
    // Windows fopen("rb")
    current offset: 16, ret:16 [54 68 69 73 20 69 73 20 61 20 41 6c 69 6e 65 0d ]
    current offset: 32, ret:16 [0a 54 68 69 73 20 69 73 20 61 20 42 6c 69 6e 65 ]
    current offset: 32, ret:0 []

    fopen类文件流接口来自C标准库,差异性源头在于Windows和Linux下编译时所采用的libc库不同,实现也有差异!


本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!