2016-11-19 3 views
-1

Я написал в файл (с помощью 'FWRITE()') следующее:Как я могу прочитать и получить разделенные данные из файла, используя 'fread' в C?

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��[email protected]������LA��[email protected]��@A��LA��[email protected]��@A������[email protected]��@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) 

и шестнадцатеричного этого будет:

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-х символов каждого из них (т.е. ТУС и LWD) с последующим 7-поплавков, а затем повторить s снова до конца файла.

Главное: Я просто хочу, чтобы прочитать все поля, разделенные как «ТУС», «КВБ», «2.10», «3.4», «7.77» ...

И я могу использовать только ' fread() 'для этого! Сейчас я пытаюсь это:

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()', потому что я пытался слишком много бессмысленных вещей! Для записи слов (т.е. Тус) в файл, я использую это:

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

и писать поплавки, это:

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

"* слова из 3 символов *": Почему '... * 4 ...'. Это должно быть 'fread (buffer, sizeof (char) * 3 ...' или даже «nicer» 'fread (buffer, sizeof (char), 3, ...' – alk

+0

cos, когда я сохранил их в файле, каждый у одного есть символ окончания '\ 0', поэтому я пытаюсь его прочитать @alk – wj127

+0

Из дампа, который вы показываете ('TUSABQ ...'), похоже, что завершающий '\ 0'' не написан в файл. Возможно, покажите нам * clean * hex-dump файлов, созданных с помощью соответствующего демпингового инструмента, такого как 'hexdump'. – alk

ответ

1

Я бы рекомендовал использовать структуру для хранения данных каждый единица измерения:

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 для 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. 

Чтобы написать блок, используйте char массив размером STORAGE_UNIT в качестве кэша, и написать это.Итак, если у вас есть unit *one, вы можете записать его в 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! */ 
    } 

Если one является массивом unit с, а вы пишете или чтение one[k], используйте &(one[k]) (или эквивалентно one + k) вместо one.

+0

да, это сработало! мне потребовалось некоторое время, чтобы понять это, но, наконец, я понял! Большое спасибо !! – wj127

+0

@ wj127: Приятно слышать! Да, я ... слишком многословный; стена текста и все .. Кстати, есть дополнительная причина, почему использование такого буфера является хорошей идеей, и это * требования к выравниванию *. В зависимости от архитектуры оборудования некоторые типы, такие как 'float', могут не просто размещаться на * любом * адресе, но требуют, чтобы адрес был кратным небольшому числу, чтобы процессор мог правильно получить к нему доступ. (В качестве альтернативы, неприглаженные обращения могут быть очень медленными.) Используя такой буфер, вы можете безопасно упаковать свои данные в формат файла, не беспокоясь о таком выравнивании или дополнении. –

+0

нет, все в порядке! на самом деле, этот мой вопрос был о практическом, что я делаю для темы «__Operating Systems__», поэтому приятно узнать больше об этом бесплатно, и кажется, что вы много знаете об этом! Еще раз спасибо! :) – wj127

Смежные вопросы