ostream :: писать не писать всю структуру? - PullRequest
1 голос
/ 01 апреля 2012

Я пытаюсь экспортировать различные значения, такие как целые и простые структуры, в двоичный файл. Вот некоторый код:

#include &ltiostream&gt
#include &ltfstream&gt
#include &ltcstdint&gt
using namespace std;

template&ltclass T&gt void writeToStream(ostream& o, T& val)
{
    o.write((char*)&val, sizeof(T));
    cout &lt&lt o.tellp() &lt&lt endl;  //always outputs 4
}

struct foo {
    uint16_t a, b;
};

int main()
{
    foo myFoo = {42, 42};
    ofstream test("test.txt", ios::binary);
    writeToStream(test, myFoo);
    test.close();
}

Программа должна генерировать выходной файл длиной 4 байта. Но когда я открываю его, его длина составляет всего 2 байта. Если я изменю myFoo.a и myFoo.b, чтобы они содержали значения 256 или более (требуется более 1 байта для хранения), тогда файл становится длиной 4 байта. Я использую Visual Studio 11 Developer Preview для Win7; Я не проверял, происходит ли то же самое в других системах или компиляторах. Как я могу заставить его правильно выводить значения a или b ниже 256?

Ответы [ 2 ]

2 голосов
/ 01 апреля 2012

Файл может быть прочитан только программой, которая понимает формат, в котором он был сохранен. Notepad ++ не имеет представления о формате, в котором был сохранен ваш файл, поэтому у него нет возможности считывать его обратно и отображать его разумно. Либо запишите файл в формате, понятном Notepad ++, например в тексте ASCII, либо прочитайте файл только в программе, которая понимает формат, в котором вы его записали.

0 голосов
/ 01 апреля 2012

Я очистил ваш код следующим образом. Хотя я не знаю, почему старый код выводит два байта, новый код выводит четыре.

#include <iostream>
#include <fstream>
#include <cstdint>
using std::cout;
using std::endl;
using std::uint16_t;
using std::ostream;
using std::ofstream;
using std::ios;

template <class T> void writeToStream(ostream& o, T& val)
{
    o.write(reinterpret_cast<char *>(&val), sizeof(T));
    cout << o.tellp() << endl;  //always outputs 4
}

struct foo {
    uint16_t a, b;
};

int main()
{
    foo myFoo = {42, 42};
    ofstream test("test.txt", ios::binary);
    writeToStream(test, myFoo);
    // Just let the stream "test" pass out of scope.
    // It closes automatically.
    //test.close();
    return 0;
}

(В моей стандартной библиотеке нет cstdint, , поэтому я использовал short вместо uint16_t,, но я сомневаюсь, что это важно.)

Тип std::ofstream является производным от std::ostream. Функция writeToStream() является более счастливой или, по крайней мере, более регулярной и более общей, если передана простой std::ostream. Также, для информации: выпускать using namespace std; почти никогда не рекомендуется в C ++.

Удачи.

...