Форум программистов, компьютерный форум, киберфорум
Наши страницы
С++ для начинающих
Войти
Регистрация
Восстановить пароль
 
 
smertnik
1 / 1 / 0
Регистрация: 06.08.2008
Сообщений: 55
#1

Некорректно читаются данные из бинарного файла - C++

30.08.2012, 01:00. Просмотров 2567. Ответов 29
Метки нет (Все метки)

столкнулся с такой проблемой и не могу найти ей объяснение.
есть код читающий содержимое двоичного файла:
C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <fcntl.h>
#include <sys\stat.h>
char *bytef;
void read_f()
{
    FILE *openfile;
    openfile=fopen(path.c_str(),"rb");
    if (openfile)
    {
        struct stat statbuf;
        stat(path.c_str(),&statbuf);
        bytef=new char[statbuf.st_size];
        fread (bytef,statbuf.st_size,1,openfile);
    };
fclose(openfile);
}
}
чтение происходит без ошибок, но сделав паузу и просматривая содержимое переменной bytef наблюдаю
появление символов '\n' там где их в реале нет! при записи содержимого переменной в файл, обнаружил закономерность:
символ '\n' , 0D в шестнадцатиречиной системе, появляется только перед символом 0A который непечатаемый, но в файле есть! и после чтения из файла bytef становится больше на добавленное количество символов! сделал цикл вырезающий '\n' перед 0А, но при записи в файл у меня '\n' начало затирать байты перед 0А вобще бред какой-то... пробовал читать из файла и писать разными методами (read, fread) и в разные переменные просто мистика какая-то...
http://www.cyberforum.ru/cpp-beginners/thread526320.html
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
30.08.2012, 01:00
Я подобрал для вас темы с готовыми решениями и ответами на вопрос Некорректно читаются данные из бинарного файла (C++):

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

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

Записать\прочесть данные в\из бинарного файла в инкапсулированну структуру
Здравствуйте форумчане. Как записать\прочесть данные в\из бинарного файла в...

Создание бинарного дерева из бинарного файла
struct Bin { string name; string city; int players; int score; };...

Создание бинарного дерево из бинарного файла
struct Bin { string name; string city; int players; int...

29
alsav22
5438 / 4833 / 831
Регистрация: 04.06.2011
Сообщений: 13,587
30.08.2012, 01:12 #2
Тут разница между бинарным чтением/записью и текстовым. При текстовом чтении/записи перевод строки в Windows и DOS состоит из двух символов: \r\n (13 и 10), в UNIX - из одного \n (10), в Mac OS - из одного \r (13). Именно 0D - это '\r', а '\n' - 0A. При текстовам чтении/записи \r\n обрабатываются в Windows как один символ '\n', при бинарном - как два байта со значениями 0D и 0A. Поэтому, если в текстовом файле делается перевод строки, то это добавляет, для бинарного чтения, дополнительные два байта.
1
alsav22
5438 / 4833 / 831
Регистрация: 04.06.2011
Сообщений: 13,587
30.08.2012, 01:39 #3
Предположим есть файл с тремя строками:
C++
1
2
3
12345
12345
12345
После каждой строки, кроме последней, нажимался Enter. Тогда такой код:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <iostream>
#include <fstream>
using namespace std;
 
 
 int main()
{
    fstream f("1.txt", ios::in | ios::binary);
    char ch;
    while (f.read(&ch, 1))
    {
        cout << hex << uppercase << (int)ch << " ";
        if (ch == '\n') cout << endl;
    }
    
    cout << endl;
    system("pause");
    return 0;
}
выведет на консоль следующее:
0
Миниатюры
Некорректно читаются данные из бинарного файла  
alsav22
5438 / 4833 / 831
Регистрация: 04.06.2011
Сообщений: 13,587
30.08.2012, 02:04 #4
Этот код ещё и запишет содержимое файла "1.txt" в файл "2.txt", но без символов '\r' и '\n'. В файле "2.txt" будет:
C++
1
123451234512345
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
#include <iostream>
#include <fstream>
using namespace std;
 
 
 int main()
{
    fstream f("1.txt", ios::in | ios::binary);
    fstream fw("2.txt", ios::out | ios::binary);
    char ch;
    while (f.read(&ch, 1))
    {
        cout << hex << uppercase << (int)ch << " ";
        if (ch == '\n') cout << endl;
        
        if (ch != '\r' && ch != '\n')
            fw.write((const char*)&ch, 1);
    }
    f.close();
    fw.close();
    
    fw.open("2.txt", ios::in | ios::binary);
    
    cout << endl << endl;
    while (fw.read(&ch, 1))
    {
        cout << hex << uppercase << (int)ch << " ";
        if (ch == '\n') cout << endl;
    }
    
    fw.close();
    
    cout << endl;
    system("pause");
    return 0;
}
0
Миниатюры
Некорректно читаются данные из бинарного файла  
smertnik
1 / 1 / 0
Регистрация: 06.08.2008
Сообщений: 55
30.08.2012, 02:26  [ТС] #5
то есть чтоб у меня файл читался правильно мне нужно открывать его в текстовом формате? но у меня содержимое бинарное! то есть там встречается вся таблица ASCII! косяков не будет???
0
alsav22
5438 / 4833 / 831
Регистрация: 04.06.2011
Сообщений: 13,587
30.08.2012, 02:30 #6
Цитата Сообщение от smertnik Посмотреть сообщение
то есть чтоб у меня файл читался правильно мне нужно открывать его в текстовом формате?
Я где-то в текстовом формате открываю? И что значит:"...читался правильно..." ? Что, вообще, нужно получить? В чём задача?
0
smertnik
1 / 1 / 0
Регистрация: 06.08.2008
Сообщений: 55
30.08.2012, 08:50  [ТС] #7
я читаю данные файла, потом содержимое буфера перегоняю в биты и уже веду работу с последовательностью бит! и символ '\n' лишний! вобщем остановлюсь наверное на вырезании его! спасибо за помощь, через часик на коде все проверю!
0
alsav22
5438 / 4833 / 831
Регистрация: 04.06.2011
Сообщений: 13,587
30.08.2012, 09:03 #8
Цитата Сообщение от smertnik Посмотреть сообщение
символ '\n' лишний! вобщем остановлюсь наверное на вырезании его!
Не забудьте тогда и '\r' вырезать. Каким методом заполняется сам файл? Возможны варианты, когда в конце ещё и '\0' будет, а в начале строки, например, '\t'. В общем, про другие управляющие символы не забывайте.
0
smertnik
1 / 1 / 0
Регистрация: 06.08.2008
Сообщений: 55
30.08.2012, 11:32  [ТС] #9
там всякие символы попадаются, но они бед не создают! мне важно любой символ в биты перегнать, а 0D просто лишним появлялся! вобщем я испробовал все комбинации fread fwrite, handle read write, в различных режимах и чтения и записи и везде такой косяк... но вот предложенный вариант с fstream дал то что нужно! причем в буфере 0D есть, а при записи его уже нет! с буфера его убрать уже не проблема! конструкция получилась такая:
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
#include <iostream>
#include <fstream>
#include <sys\stat.h>
using namespace std;
char *bytef; 
 
 int main()
{
    int length;
    struct stat statbuf;
    stat(path.c_str(),&statbuf);
    bytef=new char[statbuf.st_size];   \\в примере размер файла 369 байт
 
    fstream f(path.c_str(), ios::in | ios::binary);
    fstream fw("rez.txt", ios::out | ios::binary);
    
    f.read(bytef, statbuf.st_size);
    length=strlen(bytef);     \\после чтения bytef стал 374 байта (+5 0D)
    fw.write(bytef, statbuf.st_size);    \\записал 369 байт и получилась копия path.c_str() без 0D
 
    f.close();
    fw.close();
    
    return 0;
}
0
alsav22
5438 / 4833 / 831
Регистрация: 04.06.2011
Сообщений: 13,587
30.08.2012, 12:13 #10
Цитата Сообщение от smertnik Посмотреть сообщение
записал 369 байт и получилась копия path.c_str() без 0D
У вас в файле, что один 0D? А 0А куда дели? Если вы записали на 5 байт меньше, это не значит, что избавились от 5 символов 0D. Я не вижу в коде, как происходит избавление от 0D и от 0А. Как определяете размер файла? Если у вас файл 369 байтов, откуда появляются ещё 5? strlen() показывает количество печатных символов, без '\n' и '\r'.

Добавлено через 13 минут
Для того, чтобы узнать сколько байт в файле, нужно открыть его для чтения в бинарном режиме и сделать следующее:
C++
1
2
3
fstream f("1.txt", ios::in | ios::binary);
f.seekg(0, ios::end);
cout << f.tellg() << endl;
Добавлено через 11 минут
Я не знаю способа избавиться, при бинарном чтении/записи, от определённых символов, кроме как побайтового чтения/записи и анализа каждого байта, или обработки считанного массива для избавления от ненужных символов и последующей записи в файл.
0
smertnik
1 / 1 / 0
Регистрация: 06.08.2008
Сообщений: 55
30.08.2012, 12:40  [ТС] #11
да... тема на грани абсурда... размер файла я беру в stat(path.c_str(),&statbuf); не открывая его!
в моем конкретном файле 5 0A и соответственно в буфер добавляется 5 0D! но при записи в файл без каких либо преобразований как написано выше, записывается буфер без 0D! записывается ровно то что было в исходном файле! я сверяю по hex кодам! мистика но работает! я бы скинул образец, но трудно перенести файл на эту машину...
strlen() у меня почему-то возвращает количество символов в bytef с учетом всех что там есть!
избавляюсь я от 0D в отдельном цикле, делаю новый массив в котором пропускаю 0D если после него стоит 0A, но это уже другая история! пишу я в fw буфер без каких либо изменений! я постараюсь после обеда выложить образец!
0
alsav22
5438 / 4833 / 831
Регистрация: 04.06.2011
Сообщений: 13,587
30.08.2012, 12:49 #12
У вас Windows? IDE какая?

Добавлено через 3 минуты
Цитата Сообщение от smertnik Посмотреть сообщение
но при записи в файл без каких либо преобразований как написано выше, записывается буфер без 0D!
В программировании чудес не бывает. Если есть в буфере символы, то они, при бинарной записи, все и запишутся, если нет, то нет. Я в первых постах специально показал, что считывается/записывается при бинарном чтении/записи.
0
smertnik
1 / 1 / 0
Регистрация: 06.08.2008
Сообщений: 55
30.08.2012, 13:22  [ТС] #13
XP стоит и C++ Builder 6.0.
про чудеса я все прекрасно понимаю! поэтому и не успокаиваюсь на достигнутом! хочу понять почему именно так! ведь по логике эти строчки
length=strlen(bytef); \\после чтения bytef стал 374 байта (+5 0D)
fw.write(bytef, statbuf.st_size); \\записал 369 байт и получилась копия path.c_str() без 0D
должны в fw записать первые 369 байт из bytef, а оставшиеся 5 не трогать! эти 0D не в конце, а по буферу раскинуты, а он их убирает! исходный и результирующие файлы полностью идентичны!
вот образец!

P.S. паковал потому как на сервер не подгружался...
0
Вложения
Тип файла: rar all_res.rar (441 байт, 3 просмотров)
alsav22
5438 / 4833 / 831
Регистрация: 04.06.2011
Сообщений: 13,587
30.08.2012, 15:02 #14
Цитата Сообщение от smertnik Посмотреть сообщение
исходный и результирующие файлы полностью идентичны!
Не пойму. Если идентичны, и в исходном фале управляющие символы были, то значит они никуда и не делись? Позже посмотрю архив. Сейчас ухожу.

Добавлено через 11 минут
Никаких 0D в файле нет. Есть 5 0A. И 369 байт - это вместе с пятью 0A. Интересно, куда делись 0D ? Сам файл как изготовлялся? В Windows или может в UNIX ? Там символ новой строки - один символ 0A. Подробнее позже.

Добавлено через 1 час 16 минут
В этом файле текстовые строки записаны или просто какие-то значения? Ведь коды 0A и 0D трактуются как управляющие символы, если речь идёт о тексте, а если это файл неких значений, то 0A и 0D это просто байты со значением 10 и 13. Удаление их, в таком случае, будет ошибкой.
0
smertnik
1 / 1 / 0
Регистрация: 06.08.2008
Сообщений: 55
30.08.2012, 15:45  [ТС] #15
это исходный файл делается он в винде, но пишется в него поток бит с устройства! при чтении его в буфере появляется символ 0D перед каждым 0A! и при записи как в моем первом посте, в результирующем файле получается 0D перед каждым 0A! работает только Ваш пример! причем в буфере который пишу в файл 0D есть!
0
alsav22
5438 / 4833 / 831
Регистрация: 04.06.2011
Сообщений: 13,587
30.08.2012, 16:39 #16
Немного переделанный ваш код из первого поста:
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
#include <fcntl.h>
#include <sys\stat.h>
#include <iostream>
#include <fstream>
using namespace std;
 
char *bytef;
void read_f()
{
    FILE *openfile;
    openfile = fopen("all_res.bin", "rb");
    if (openfile)
    {
        //struct stat statbuf;
        //stat(path.c_str(), &statbuf);
        bytef = new char[369];
        fread (bytef, 369, 1, openfile);
    }
 
    fclose(openfile);
}
 
 int main()
 {
    read_f();
    int n = 0;
    for (int i = 0; i < 369; i++) // вывод на консоль содержимого bytef
    {
         cout << hex << uppercase << (int)((unsigned char)bytef[i]) << ' ';
         if (bytef[i] == 0x0D) n++; // если встретился байт со занчением 0D.
    }
 
    cout << endl << endl << "D = " << n << endl; // сколько встретилось 0D.
    
    system("pause");
    return 0;
 }
Вместо statbuf.st_size поставил 369 и закоментировал структуру, потому что у меня её нет. Результат работы. Побайтовый вывод (через пробел) содержимого буфера bytef, после считывания в него файла. Вывод количетсва найденных байтов со значением 0D.
0
Миниатюры
Некорректно читаются данные из бинарного файла  
alsav22
5438 / 4833 / 831
Регистрация: 04.06.2011
Сообщений: 13,587
30.08.2012, 17:01 #17
Код из 9 поста. Результат тот же. Никаких 0D в буфере нет.
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
#include <iostream>
#include <fstream>
#include <sys\stat.h>
using namespace std;
 
char *bytef; 
 
 int main()
{
    //int length;
    //struct stat statbuf;
    //stat(path.c_str(),&statbuf);
    bytef = new char[369]; // размер файла 369 байт
 
    fstream f("all_res.bin", ios::in | ios::binary);
    fstream fw("rez.bin", ios::out | ios::binary);
    
    f.read(bytef, 369); // считал 369 байт.
    //length=strlen(bytef); Непременимо. Даёт ошибку, так как в bytef не строка.
    fw.write(bytef, 369);   // записал 369 байт. 
    f.close();
    fw.close();
 
    int n = 0;
    for (int i = 0; i < 369; i++) // вывод на консоль содержимого bytef
    {
         cout << hex << uppercase << (int)((unsigned char)bytef[i]) << ' ';
         if (bytef[i] == 0x0D) n++; // если встретился байт со занчением 0D.
    }
 
    cout << endl << endl << "D = " << n << endl; // сколько встретилось 0D.
    
    system("pause");
    return 0;
}
0
Миниатюры
Некорректно читаются данные из бинарного файла  
smertnik
1 / 1 / 0
Регистрация: 06.08.2008
Сообщений: 55
30.08.2012, 17:13  [ТС] #18
уже мозг кипит... сейчас остановил программу посмотрел в буфере уже нет этих символов! но они 100% были! потому как при дальнейшей обработке у меня вылезали лишние биты! именно по коду 0D! тоже сделал счетчик он не находит 0D, но еще раз повторюсь они были в буфере если остановить выполнение и просмотреть его содержимое! но при записи в файл моим способом 0D появляется! но это уже объясняется постом в самом начале! fstream решает эту проблему! ну вот вроде разобрались! спасибо большое!

я уже писал что ваш метод через fstream работает как надо!
0
alsav22
5438 / 4833 / 831
Регистрация: 04.06.2011
Сообщений: 13,587
30.08.2012, 17:46 #19
Цитата Сообщение от smertnik Посмотреть сообщение
но при записи в файл моим способом 0D появляется!
Я уже не со своим кодом разбираюсь, а с вашим. В 16 посте ваш код из первого поста, там нет fstream и всё так же работает нормально. Никаких дополнительных символов. Вы когда пишите:
Цитата Сообщение от smertnik Посмотреть сообщение
но при записи в файл моим способом 0D появляется!
, имеете ввиду, запись в файл, того что считали в bytef ?
Потом вот это:
Цитата Сообщение от smertnik Посмотреть сообщение
но еще раз повторюсь они были в буфере если остановить выполнение и просмотреть его содержимое!
В какой момент остановку делали? Может это заморочки отладчика, что-нибудь не то показывал?
Что-то странное... Не могут байты неизвестно откуда появляться.
0
smertnik
1 / 1 / 0
Регистрация: 06.08.2008
Сообщений: 55
30.08.2012, 18:27  [ТС] #20
имеете ввиду, запись в файл, того что считали в bytef ? ------ да именно так! писал и fwrite и write.

В какой момент остановку делали? ------ после чтения буфера и перед записью в файл.

Может это заморочки отладчика, что-нибудь не то показывал? ------ там содержимое файла один в один но с добавкой 0D.

у меня мысли такие: fwrite и write пишут по правилам из второго поста и поэтому добавляют 0D
0
30.08.2012, 18:27
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
30.08.2012, 18:27
Привет! Вот еще темы с решениями:

Чтение из файла, не все числа читаются в потоке
Здравствуйте! Написал программку которая создает массив из случайных символов,...

Построение идеально сбалансированного дерева, значения читаются из текстового файла
Разработать программу построения идеально сбалансированного дерева, элементами...

Строки читаются из текстового файла функцией fgets и указатели на них помещаются в структуру данных...
Вообщем вот такое задание: Строки читаются из текстового файла функцией fgets и...

Некорректно выводятся данные
в програмке не выводятся значения для y. на экран выводится как x= -5.00...


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

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

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