Rover12421's Blog

The End.

fread读取ANSI文本遇到回车偏移的问题

        最近一个项目在做文本字符串优化的时候,想把字符串保存在文本,然后用的时候从文本中读取一行,再显示出来。本来这是个很简单的问题,结果调试的时候发现一遇到多个回车就出现偏移问题,真是头疼。最后发现是fread读取回车符的问题。

      ANSI文本的回车是由'\r\n'(\x0D\x0A)两个字节来表示的,但是fread会把他们当成一个字节来读取,而且不管是从'\r\n'的那个读起,fread都出来的都是'\n',如果偏移是自己计算的话,就会出现问题。

fileSeek = 0;
fseek(fp,fileSeek,SEEK_SET);
fread(oneChar,sizeof(char),1,fp);
fileSeek++;
fread(oneChar,sizeof(char),1,fp);
fileSeek++;

例如这几语句,假设文本test.txt的内容如下:

test.txt

abcd

用C32等16进制编辑器打开,可以看到他的Hex值为:

Hex存储
0D0A61626364

如果用上面的代码图取这个文本,想想oneChar[0]第一次和第二次的内容分别是什么,文件指针的实际偏移是多少?

我一开始也以为一次oneChar[0]的内容为'0x0D',第二次oneChar[0]的内容为'0x0A'.但是实际中让我郁闷了很久。

实际是,oneChar[0]第一次的内容为'0x0A',第二次的内容是'0x61'.

再来说文件指针的实际偏移,第一次文件的实际偏移已经为2了,但是fileSeek却还等于1.第二次文件实际偏移为3,fileSeek为2.

最后给出个测试文件. VS2010下新建windows控制台程序。

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
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
#include “stdafx.h” 
#include

int _tmain(int argc, _TCHAR argv[])
{
    TCHAR fpFile = _T(test.txt);
    FILE fp;
    errno_t err;
    int lineLen = ;
    int fileSeek = ;
    char lineStr;
    char oneChar[100];

    err = _tfopen_s(&fp, fpFile, _T(r));
    if (err != )
    {
        _tprintf(_T(Open the file %s error.\n), fpFile);
        return ;
    }

    while(!feof(fp))
    {
        ZeroMemory(oneChar,sizeof(oneChar));
        fseek(fp,fileSeek+lineLen,SEEK_SET);
        //fseek(fp,fileSeek,SEEK_SET); 
        fread(oneChar,sizeof(char),1,fp);
        if (oneChar[] == ‘\n || feof(fp))
        {
            if (lineLen > )
            {
                lineStr = new char[lineLen+1];
                ZeroMemory(lineStr,lineLen+1);
                fseek(fp,fileSeek,SEEK_SET);
                fread(lineStr,sizeof(char),lineLen,fp);
                printf(lineStr:%s\n,lineStr);
                delete []lineStr;
            }
            else
            {
                fileSeek ++;
            }
        }
        else
        {
            lineLen++;
        }
    }
    return ;
}

注意下面两句:

1
2
    fseek(fp,fileSeek+lineLen,SEEK_SET);
    //fseek(fp,fileSeek,SEEK_SET);

Comments