如何在C中使用'fread'从文件中读取和获取分离的数据?

我've written in a file (using ' fwrite() ')以下内容:

TUS�ABQ���������������(A����������(A��B������(A��B���A��(A��B���A������B���A������0����A������0�ABQ�������0�ABQ�����LAS����������������A�����������A��&B�������A��&B��B���A��&B��B������&B��
B����153���B����153�LAS�����153�LAS�����LAX���������������:A����������:AUUB������:AUUB��B��:
AUUB��B����UUB��B����������B��������LAX���������LAX�����MDW���������������A����������A��(�������A��(����A��A��(����A������(����A����A�89���A����A�89MDW�����A�89MDW�����OAK���������
����������������������@�����������@�����������@�����������@�������������������������OAK���������OAK�����SAN���������������LA����������LA��P@������LA��P@��@A��LA��P@��@A������P@��@A����������@A��������SAN���������SAN�����TPA�ABQ����������������B�����������B��@�����...(continues)

这被翻译成:

TUSLWD2.103.47.775.1904.06.40.03AMBRFD4.63.228.935.0043.09.113.0ASDGHU5.226.47.78.3.26...(The same structure)

并且hexdump将是:

00000000  54 55 53 00 41 42 51 00  00 00 00 00 00 00 00 00  |TUS.ABQ.........|
00000010  00 00 00 00 00 00 28 41  00 00 0e 42 00 00 f8 41  |......(A...B...A|
00000020  00 00 00 00 4c 41 53 00  00 00 00 00 00 00 00 00  |....LAS.........|
00000030  00 00 00 00 00 00 88 41  00 00 26 42 9a 99 11 42  |.......A..&B...B|
(Continues...)

结构是,总是2个单词,每个3个字符(即TUS和LWD),然后是7个浮点数,然后它再次重复,直到文件末尾 .

关键是:我只想读取每个分隔的字段,如'TUS','LWD','2.10','3.4','7.77'......

我只能使用' fread() ' to achieve that! For now, I' m尝试这个:

aux2 = 0;
fseek(fp, SEEK_SET, 0);
fileSize = 0;
while (!feof(fp) && aux<=2) {
    fread(buffer, sizeof(char)*4, 1, fp);
    printf("%s", buffer);
    fread(buffer, sizeof(char)*4, 1, fp);
    printf("%s", buffer);
    for(i=0; i<7; i++){
        fread(&delay, sizeof(float), 1, fp);
        printf("%f", delay);
    }
    printf("\n");
    aux++;
    fseek(fp,sizeof(char)*7+sizeof(float)*7,SEEK_SET);
    aux2+=36;
}

我得到了这个结果:

TUSABQ0.0000000.0000000.00000010.5000000.0000000.00000010.500000
AB0.0000000.000000-10384675421112248092159136000638976.0000000.0000000.000000-10384675421112248092159136000638976.0000000.000000
AB0.0000000.000000-10384675421112248092159136000638976.0000000.0000000.000000-10384675421112248092159136000638976.0000000.000000

但它无法正常工作......

*注意:忘记上一次' fseek() ', cos I'的争论已经尝试了太多无意义的事情!要将单词(即TUS)写入文件,我使用:

fwrite(x->data->key, 4, sizeof(char), fp);

并写下花车,这个:

for (i = 0; i < 7; i++) {
    fwrite(&current->data->retrasos[i], sizeof(float), sizeof(float), fp);
}

回答(1)

2 years ago

我建议使用一个结构来保存每个数据单元:

typedef struct {
    float  value[7];
    char   word1[5];  /* 4 + '\0' */
    char   word2[5];  /* 4 + '\0' */
} unit;

要使文件格式可移植,您需要一个函数将上述结构打包和解包到36字节数组中 . 在Intel和AMD架构上, float 对应于小端字节顺序的IEEE-754-2008 binary32格式 . 例如,

#define STORAGE_UNIT (4+4+7*4)

#if defined(__i386) || defined(_M_IX86) || defined(__x86_64__) || defined(_M_X64)

size_t unit_pack(char *target, const size_t target_len, const unit *source)
{
    size_t i;

    if (!target || target_len < STORAGE_UNIT || !source) {
        errno = EINVAL;
        return 0;
    }

    memcpy(target + 0, source->word1, 4);
    memcpy(target + 4, source->word2, 4);

    for (i = 0; i < 7; i++)
        memcpy(target + 8 + 4*i, &(source->value[i]), 4);

    return STORAGE_UNIT;
}

size_t unit_unpack(unit *target, const char *source, const size_t source_len)
{
    size_t i;

    if (!target || !source || source_len < STORAGE_UNIT) {
        errno = EINVAL;
        return 0;
    }

    memcpy(target->word1, source, 4);
    target->word1[4] = '\0';

    memcpy(target->word2, source + 4, 4);
    target->word2[4] = '\0';

    for (i = 0; i < 7; i++)
        memcpy(&(target->value[i]), source + 8 + i*4, 4);

    return STORAGE_UNIT;
}

#else
#error Unsupported architecture!
#endif

以上仅适用于Intel和AMD机器,但如果有必要,它很容易扩展到其他架构 . (目前几乎所有机器都使用IEEE 754-2008 binary32 for float ,只有字节顺序不同 . 那些没有,通常有C扩展,可以转换为内部格式 . )

使用上面的,你可以 - 应该!必须! - 记录您的文件格式,例如:

Words are 4 bytes encoded in UTF-8
Floats are IEEE 754-2008 binary32 values in little-endian byte order

A file contains one or more units. Each unit comprises of

    Name    Description
    word1   First word
    word2   Second word
    value0  First float
    value1  Second float
    value2  Third float
    value3  Fourth float
    value4  Fifth float
    value5  Sixth float
    value6  Second float

There is no padding.

要编写单元,请使用大小为 STORAGE_UNITchar 数组作为缓存,然后编写 . 所以,如果你有 unit *one ,你可以用 FILE *out 把它写成 FILE *out

char  buffer[STORAGE_UNIT];

    if (unit_pack(buffer, sizeof buffer, one)) {
        /* Error! Abort program! */
    }
    if (fwrite(buffer, STORAGE_UNIT, 1, out) != 1) {
        /* Write error! Abort program! */
    }

相应地,从 FILE *in 读取

char buffer[STORAGE_UNIT];

    if (fread(buffer, STORAGE_UNIT, 1, in) != 1) {
        /* End of file, or read error.
           Check feof(in) or/and ferror(in). */
    }
    if (unit_unpack(one, buffer, STORAGE_UNIT)) {
        /* Error! Abort program! */
    }

如果 oneunit 的数组,并且您正在编写或读取 one[k] ,请使用 &(one[k]) (或等效 one + k )而不是 one .