Проблема записи двоичного файла в C ++ - PullRequest
2 голосов
/ 23 марта 2011

Это моя функция, которая создает двоичный файл

void writefile()
{
    ofstream myfile ("data.abc", ios::out | ios::binary);
    streamoff offset = 1;
    if(myfile.is_open())
    {
        char c='A';
        myfile.write(&c, offset );
        c='B';
        myfile.write(&c, offset );
        c='C';
        myfile.write(&c,offset);
        myfile.write(StartAddr,streamoff (16) );
        myfile.close();
    }
     else
         cout << "Some error" << endl ;
}

Значение StartAddr равно 1000, следовательно, ожидаемый выходной файл: A B C 1000 NUL NUL NUL

Однако, как ни странно, мой выходной файл добавляет это: data.abc

Итак, окончательный результат: A B C 1000 NUL NUL NUL data.abc

Пожалуйста, помогите мне с этим. Как с этим бороться? Почему это странное поведение?

Ответы [ 3 ]

2 голосов
/ 24 марта 2011

Я рекомендую вам прекратить двоичную запись и работать над записью данных в текстовом формате. Вы уже столкнулись с некоторыми проблемами при записи данных . У вас все еще есть проблемы с чтением данных и переносимостью. Ожидайте больше боли, если продолжите этот маршрут.

Используйте текстовые представления. Для простоты вы можете поместить одно поле в строку и использовать std::getline для чтения. Текстовое представление позволяет легко просматривать данные в любом текстовом редакторе. Попробуйте использовать Notepad для просмотра двоичного файла файл!

Да, но двоичные данные работают намного быстрее и занимают меньше места в файле. Вы уже потратили достаточно времени и денег, чем могли бы получить, используя двоичные данные. Скорость компьютеров и огромные объемы памяти (диска и оперативной памяти) делают двоичные представления делом прошлого (за исключением крайних случаев).

В качестве учебного пособия используйте двоичный код. Для простоты разработки и быстрых графиков (IOW, досрочное завершение) используйте текстовые представления.

Переполнение стека поиска для «микрооптимизации C ++» для обоснований.

1 голос
/ 24 марта 2011

Есть несколько проблем с этим кодом.

Для начала, если вы хотите записать отдельные символы в поток, вам не нужно использовать ostream :: write.Вместо этого просто используйте ostream :: put, как показано здесь:

myfile.put('A');

Во-вторых, если вы хотите записать строку в поток файлов, просто используйте оператор вставки потока:

myfile << StartAddr;

Это совершенно безопасно, даже в двоичном режиме.

Что касается конкретной проблемы, о которой вы сообщаете, я думаю, что проблема в том, что вы пытаетесь записать строку длины четыре (StartAddr), но вы сказали потоку записать шестнадцать байтов.Это означает, что вы записываете четыре байта для содержимого строки, затем нулевой терминатор и затем девять байтов всего, что происходит в памяти после буфера.В вашем случае это еще два нулевых байта, а не бессмысленный текст, который вы увидели после этого.Чтобы это исправить, либо измените код, чтобы он записывал меньше байтов, либо, если StartAddr - строка, просто напишите его, используя <<. </p>

0 голосов
/ 24 марта 2011

В строке myfile.write(StartAddr,streamoff (16) ); вы указываете объекту myfile записать 16 байтов в поток, начиная с адреса StartAddr. Представьте, что StartAddr - это массив из 16 байтов:

char StartAddr[16] = "1000\0\0\0data.b32\0";
myfile.write(StartAddr, sizeof(StartAddr));

Будет генерировать вывод, который вы видите. Не видя объявления / определения StartAddr, я не могу сказать наверняка, но, похоже, вы пишете пятибайтовую строку с нулевым завершением "1000", за которой следует то, что происходит в следующих 11 байтах после StartAddr. В этом случае появляется пара нулевых байтов, за которыми следует постоянная строка с нулевым окончанием "data.b32" (которую компилятор должен поместить где-то в памяти) - это то, что следует за StartAddr.

Несмотря ни на что, ясно, что вы перегрузили буфер.

Если вы пытаетесь записать 16-битное целочисленное значение в поток, у вас есть пара опций, обе из которых основаны на том факте, что в байте обычно 8 бит. Самым «чистым» будет что-то вроде:

char x = (StartAddr & 0xFF);
myfile.write(x);
x = (StartAddr >> 8);
myfile.write(x);

Предполагается, что StartAddr является 16-разрядным целочисленным типом и не учитывает возможный перевод (например, потенциальное преобразование значения 10 [перевод строки) в последовательность возврата каретки / перевода строки).

Кроме того, вы можете написать что-то вроде:

myfile.write(reinterpret_cast<char*>(&StartAddr), sizeof(StartAddr));
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...