C запись в двоичный файл с помощью ofstream

#c #binary #ofstream

#c #двоичный #ofstream

Вопрос:

Для небольшого формата файла, который я разрабатываю, мне нужно вывести заголовок размером 519 байт в файл. Я немного новичок во всей концепции ofstream. Хотя у меня есть некоторый опыт чтения заголовка файла Targa Truevision. Но вывод — это то, с чем я далеко не знаком.

Итак, в основном, вот моя проблема.

Я открыл экземпляр ofstream, и мне нужно вывести заголовок следующим образом:

 typedef struct header {
    char      version;   // offset 0, length 1
    short int width;     // offset 1, length 2
    short int height;    // offset 3, length 2
    short int pathlen;   // offset 5, length 2
    char      desc[512]; // offset 7, length 512
} fileHeader;
 

Теперь мне нужно получить все это в первых 519 байтах файла, остальное содержимое меняется, как бы я мог скопировать этот заголовок в свой файл?

Я предпочтительно хочу сделать это с помощью класса ofstream, но я также в порядке с оригинальной библиотекой C. Я занимаюсь этим уже 2 часа, и пока ничего не добился, и попытки поиска в Google тоже не очень помогают.

Ответ №1:

 std::ofstreamamp; operator<<(std::ofstreamamp; out, const headeramp; myheader) {
    out.write((char*)amp;myheader.version, sizeof(myheader.version));
    out.write((char*)amp;myheader.width, sizeof(myheader.width));
    out.write((char*)amp;myheader.height, sizeof(myheader.height));
    out.write((char*)amp;myheader.pathlen, sizeof(myheader.pathlen));
    out.write((char*)amp;myheader.desc, sizeof(myheader.desc));
    return out;
}
std::ifstreamamp; operator>>(std::ifstreamamp; in, headeramp; myheader) {
    in.read((char*)amp;myheader.version, sizeof(myheader.version));
    in.read((char*)amp;myheader.width, sizeof(myheader.width));
    in.read((char*)amp;myheader.height, sizeof(myheader.height));
    in.read((char*)amp;myheader.pathlen, sizeof(myheader.pathlen));
    in.read((char*)amp;myheader.desc, sizeof(myheader.desc));
    return in;
}

int main() {
    std::cout << fileHeader << 'n';
    std::cin >> fileHeader;
    return 0;
}
 

Поскольку у вас нет указателей, это довольно просто! (Обратите внимание, что это работает только с узкими потоками)
Еще один пример, показывающий вещи с текстом и динамической памятью / указателями / etc

 class thing {
    std::string name;
    int height;
    friend std::ofstreamamp; operator<<(std::ofstreamamp; out, const thing amp; myheader);
    friend std::ifstreamamp; operator>>(std::ifstreamamp; in, thing amp; myheader);
public: 
    thing() {}
};

std::ofstreamamp; operator<<(std::ofstreamamp; out, const thing amp; myheader) {
    thing << name.size() << ' ';
    thing.write(amp;name[0], name.size()) << ' ' << height;
} 
std::ifstreamamp; operator>>(std::ifstreamamp; in, thing amp; myheader) {
    int size;
    in >> size;
    myheader.name.resize(size);
    in.read(amp;myheader.name[0], name.size());
    return in >> myheader.height;        
} 
 

Комментарии:

1. Это приведение может привести к проблемам, если структура отформатирована неправильно.

2. Хотя я ценю ваш ответ, я хотел бы получить объяснение того, как это работает. Как я могу быть уверен, что данные записаны в правильном порядке (сначала версия, затем ширина и т. Д.). Кроме того, почему-то эта функция мне кажется неправильной. Что-то не так.

3. Вы (оба) правы, я забыл о дополнении. Ваша структура не будет занимать 519 байт в ОЗУ, только на диске. (В Windows это было бы 520 байт) Исправлено. @user1019020: они были бы в порядке, но после байта версии был бы бессмысленный байт.

4. Если вы беспокоитесь о упаковке и выравнивании слов, рекомендуется вызывать read и write для каждого элемента структуры, а не для всего сразу. Судя по вашим смещениям, вы хотите плотно упаковать данные. Ваш символ, скорее всего, дополнен короткой границей int в вашей архитектуре.

5. @MooingDuck Да, я попробовал ваш метод, а затем прочитал свой файл обратно, ширина внезапно изменилась на 5192 или что-то в этом роде, по сравнению с 20. Я попробую ваше новое предложение. 🙂