技术问题库
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 []- 对于Windows下,fread 接口读取文件遇到 \r(0x0d)认为是换行符,0x0d不返回到用户,然后继续读取满16字节返回;
- 对于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 协议 ,转载请注明出处!