Форум программистов, компьютерный форум, киберфорум
Наши страницы
С++ для начинающих
Войти
Регистрация
Восстановить пароль
 
Рейтинг 5.00/5: Рейтинг темы: голосов - 5, средняя оценка - 5.00
Gdasar
190 / 51 / 19
Регистрация: 18.02.2013
Сообщений: 488
Записей в блоге: 9
Завершенные тесты: 1
1

Чтение бинарного файла

12.04.2017, 11:44. Просмотров 956. Ответов 11
Метки нет (Все метки)

Здравствуйте.
Есть код чтения бинарного файла:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
    FILE *f;
    string tmp;
    char buff[5] = {0};
    f = fopen("data.bin", "rb");
    if(f == NULL)
    {
        return 0;
    }
    int a;
    fread(&buff, 1, 1, f);
    tmp = buff;
    std::istringstream stream(tmp);
    stream >> std::hex >> a;
    cout << a << endl;
    strcpy(buff, "");
    _getch();
    fclose(f);
    return 0;
И в результате получаю 10. Хотя должен получить 65.
C++
1
std::istringstream stream("41");
Выводит 65 - все хорошо.

Собственно вопрос : как мне получить корректное 16-ричное число при чтении?
Спасибо за внимание.
0
Миниатюры
Чтение бинарного файла  
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
12.04.2017, 11:44
Ответы с готовыми решениями:

Чтение нескольких структур и одной переменной из бинарного файла. Формат файла имеется
Формат файла состоит из 3 структур и одной переменной. Подробное описание...

Чтение бинарного файла
Подскажите пожалуйста как можно правильно открыть бинарный файл не зная...

Чтение бинарного файла
как получить доступ к произвольному адресу файла? Нужно отправить файл через...

Чтение из бинарного файла
Здравствуйте. У меня имеется некий класс Product, объекты которого хранятся в...

Чтение бинарного файла
Добрый Добавлено через 6 минут Добрый день. Не получается прочитать бин....

11
likehood
981 / 826 / 395
Регистрация: 25.12.2016
Сообщений: 2,727
Завершенные тесты: 3
12.04.2017, 11:59 2
После вызова fread массив buf уже содержит то, что вам нужно.
C++
1
2
3
fread(&buff, 1, 1, f);
int a = buf[0];
std::cout << a;
1
Gdasar
190 / 51 / 19
Регистрация: 18.02.2013
Сообщений: 488
Записей в блоге: 9
Завершенные тесты: 1
12.04.2017, 12:08  [ТС] 3
likehood, и правда
Ещё вопрос : как мне получить число 832194 из следующего 16-ричного числа CB2C2?
C++
1
fread(&buff, 1, 5, f);
Спасибо за ответ.
0
likehood
981 / 826 / 395
Регистрация: 25.12.2016
Сообщений: 2,727
Завершенные тесты: 3
12.04.2017, 12:21 4
Цитата Сообщение от Gdasar Посмотреть сообщение
fread(&buff, 1, 5, f);
Цитата Сообщение от Gdasar Посмотреть сообщение
CB2C2
Это число занимает в памяти не 5 байтов, а 2.5, так как один байт кодируется двумя hex цифрами.

Добавлено через 1 минуту
Если считать из файла 5 байтов, то это будут байты 41 CB 2C 2C B2.

Добавлено через 2 минуты
Можно прочитать четыре байта и записать их в целое число:
C++
1
2
fread(buff, 1, 4, f); // & перед buff не нужен, buff это и так указатель
int a = *( reinterpret_cast<int*>(buff) );
Добавлено через 1 минуту
А лучше так:
C++
1
2
3
int a;
fread(&a, sizeof(a), 1, f);
std::cout << a;
1
Gdasar
190 / 51 / 19
Регистрация: 18.02.2013
Сообщений: 488
Записей в блоге: 9
Завершенные тесты: 1
12.04.2017, 12:25  [ТС] 5
likehood, понял.
А как же тогда получить нужное мне 16-ричное число?
C++
1
fread(&buff, 1, 3, f);
Вот прочитаю я следующие 3 байта
C++
1
CB2C2C
, а что дальше то? Что-то не пойму.

Добавлено через 2 минуты
В общем, стоит задача : прочитать первый байт, то есть
C++
1
41
и получить из него 2-ное число.
Далее нужно прочитать, как Вы написали, 2,5 байта и перевести их в 10-ное число.
0
likehood
981 / 826 / 395
Регистрация: 25.12.2016
Сообщений: 2,727
Завершенные тесты: 3
12.04.2017, 12:26 6
Лучший ответ Сообщение было отмечено Gdasar как решение

Решение

Перевод трёх байтов в целое число:
C++
1
int a = buff[0] + buff[1]*0x100 + buff[2]*0x10000;
Добавлено через 1 минуту
Хотя, если остальная часть массива buff забита нулями, то можно и так, как я написал выше.
1
Gdasar
190 / 51 / 19
Регистрация: 18.02.2013
Сообщений: 488
Записей в блоге: 9
Завершенные тесты: 1
12.04.2017, 12:39  [ТС] 7
Благодарю!
Изначально думал, что 16-ричное число будет проще перевести в 2-е. Но теперь думаю, что просто накотаю функцию для перевода 10-го числа в 2-е.

Добавлено через 11 минут
Вот смотрите:
содержимое бинарного файла
Код
41 CB 2C 2C B2 C7 0A 13 42 CB 2C 1C B2 C8 08 0F
41 - это 65
CB 2C 2 - это 832194
C B2 C7 -это 832199
0A - также число
13 - и это число

далее ещё такой же набор из 5 чисел.

В конце концов я должен получить все 10-ные числа, записанные в файл.
Получаю первое:
C++
1
2
fread(&buff, 1, 1, f);
a = buff[0];
Как далее мне получить 2 и 3 числа?
CB 2C 2 - это 832194
C B2 C7 -это 832199
0
likehood
981 / 826 / 395
Регистрация: 25.12.2016
Сообщений: 2,727
Завершенные тесты: 3
12.04.2017, 12:42 8
А числа точно хранятся в таком формате, с разрывом посередине байта? Как-то странно это выглядит.
0
Gdasar
190 / 51 / 19
Регистрация: 18.02.2013
Сообщений: 488
Записей в блоге: 9
Завершенные тесты: 1
12.04.2017, 12:43  [ТС] 9
likehood, да, именно так они и хранятся.
Есть идеи по поводу того, как их получить?
0
likehood
981 / 826 / 395
Регистрация: 25.12.2016
Сообщений: 2,727
Завершенные тесты: 3
12.04.2017, 13:02 10
Лучший ответ Сообщение было отмечено Gdasar как решение

Решение

Цитата Сообщение от Gdasar Посмотреть сообщение
Есть идеи по поводу того, как их получить?
Можно сначала разбить байты на половинки, а потом обратно их объединить. Например так (код не проверял).
C++
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
int join(char *buff, int n);
 
void foo()
{
    char buff[] = { 0x41, 0xCB, 0x2C, 0x2C, 0xB2, 0xC7, 0x0A, 0x13 };
    const int len = 8;
    char halfByteBuff[len*2];
 
    // split
    for (int i=0; i<len; i++)
    {
        halfByteBuff[i*2]   = buff[i] >> 4;
        halfByteBuff[i*2+1] = buff[i] & 0x0F;
    }
 
    // join
    int a = join(&halfByteBuff[0], 2); // a == 0x41
    int b = join(&halfByteBuff[2], 5); // b == 0xCB2C2
    int c = join(&halfByteBuff[7], 5); // c == 0xCB2C7
}
 
int join(char *buff, int n)
{
    int x = 0;
    for (char *p = buff+n-1; p >= buff; p--)
    {
        x = x*16 + *p;
    }
 
    return x;
}
Добавлено через 2 минуты
Только порядок байтов у меня не правильный, надо цикл в 25 строке заменить на
C++
1
for (char *p = buff; p < buff+n; p++)
1
Gdasar
190 / 51 / 19
Регистрация: 18.02.2013
Сообщений: 488
Записей в блоге: 9
Завершенные тесты: 1
12.04.2017, 16:38  [ТС] 11
likehood, как я понял:
41 - это 0100 0001
Данное выражение сдвигает первые 4 бита на 4 позиции вправо
C++
1
buff[i] >> 4
в итоге получаем 0000 0100 - это 4

Вторая операция - И(битовое И)
C++
1
buff[i] & 0x0F
0F - это 0000 1111
0100 0001 & 0000 1111 = 0000 0001

Тут вроде как все понятно Надеюсь, верно всё понял.

Вот только код
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
char buff[] = { 0x41, 0xCB, 0x2C, 0x2C, 0xB2, 0xC7, 0x0A, 0x13 };
    const int len = 8;
    char halfByteBuff[len*2];
 
    // split
    for (int i=0; i<len; i++)
    {
        halfByteBuff[i*2]   = buff[i] >> 4;
        halfByteBuff[i*2+1] = buff[i] & 0x0F;
    }
 
    // join
    int a = join(&halfByteBuff[0], 2); // a == 0x41
    int b = join(&halfByteBuff[2], 5); // b == 0xCB2C2
    int c = join(&halfByteBuff[7], 5); // c == 0xCB2C7
 
    cout << a << endl;
    cout << b << endl;
    cout << c << endl;
Выводит следующее:
65
-216382
766407
Понять не могу из-за чего так происходит.
0
likehood
981 / 826 / 395
Регистрация: 25.12.2016
Сообщений: 2,727
Завершенные тесты: 3
12.04.2017, 16:51 12
Лучший ответ Сообщение было отмечено Gdasar как решение

Решение

Нужно заменить char на unsigned char, иначе неправильно выполняется операция buff[i] >> 4.
C++
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
#include <iostream>
 
int join(unsigned char *buff, int n);
 
void foo()
{
    unsigned char buff[] = { 0x41, 0xCB, 0x2C, 0x2C, 0xB2, 0xC7, 0x0A, 0x13 };
    const int len = sizeof(buff)/sizeof(buff[0]);
    unsigned char halfByteBuff[len*2];
 
    // split
    for (int i=0; i<len; i++)
    {
        halfByteBuff[i*2]   = buff[i] >> 4;
        halfByteBuff[i*2+1] = buff[i] & 0x0F;
    }
 
    for (int i = 0; i < len*2; i++)
        std::cout << std::hex << (int) halfByteBuff[i] << ' ';
    std::cout << "\n";
 
    // join
    int a = join(&halfByteBuff[0], 2); // a == 0x41
    int b = join(&halfByteBuff[2], 5); // b == 0xCB2C2
    int c = join(&halfByteBuff[7], 5); // c == 0xCB2C7
    std::cout << std::hex << a << "\n";
    std::cout << std::hex << b << "\n";
    std::cout << std::hex << c << "\n";
}
 
int join(unsigned char *buff, int n)
{
    int x = 0;
    for (unsigned char *p = buff; p < buff+n; p++)
    {
        x = x*16 + *p;
    }
 
    return x;
}
 
int main()
{
    foo();
}
1
12.04.2017, 16:51
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
12.04.2017, 16:51

Чтение из бинарного файла
Ну собственно,у меня есть некий двоичный файл,в него записана моя информация в...

Чтение из бинарного файла
Создала Базу данных. запись в файл происходит, а чтение из файла не получается....

Чтение бинарного файла
Привет! Необходима помощь в таком вопросе - Создал программу для хранения...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
12
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2018, vBulletin Solutions, Inc.
Рейтинг@Mail.ru