boost 中的 gzip_compressor 似乎无法正确保存和加载压缩流

问题描述 投票:0回答:1
namespace io = boost::iostreams;    

void saveCompressedData(const std::string& file_path, const std::vector<double>& bid, const std::vector<double>& ask, const std::vector<double>& close_prices, const std::vector<int>& tick_numbers) {
        try {
            // Create an output file stream and filtering stream
            std::ofstream file(file_path, std::ios_base::out | std::ios_base::binary);
            if (!file) {
                std::cerr << "Error opening compressed file for writing: " << file_path << std::endl;
                return;
            }
    
            io::filtering_ostream out;
            out.push(io::gzip_compressor());
            out.push(file);
    
            // Write the data to the compressed file
            uint64_t size = bid.size();
            out.write((const char* ) (&size), sizeof(size));
            out.write(reinterpret_cast<const char*>(bid.data()), size * sizeof(double));
            out.write(reinterpret_cast<const char*>(ask.data()), size * sizeof(double));
    
            size_t close_size = close_prices.size();
            out.write(reinterpret_cast<const char*>(&close_size), sizeof(close_size));
            out.write(reinterpret_cast<const char*>(close_prices.data()), close_size * sizeof(double));
    
            size_t tick_size = tick_numbers.size();
            out.write(reinterpret_cast<const char*>(&tick_size), sizeof(tick_size));
            out.write(reinterpret_cast<const char*>(tick_numbers.data()), tick_size * sizeof(int));
            out.pop();
    
        }
        catch (const std::exception& e) {
            std::cerr << "Exception while writing compressed data: " << e.what() << std::endl;
        }
    }
    
    void loadCompressedData(const std::string& file_path, std::vector<double>& bid, std::vector<double>& ask, std::vector<double>& close_prices, std::vector<int>& tick_numbers) {
        try {
            // Create an input file stream and filtering stream
            std::ifstream file(file_path, std::ios_base::in | std::ios_base::binary);
            if (!file) {
                std::cerr << "Error opening compressed file for reading: " << file_path << std::endl;
                return;
            }
    
            io::filtering_istream in;
            in.push(io::gzip_decompressor());
            in.push(file);
    
            // Read the data from the compressed file
            uint64_t size;
            in.read((char*)(&size), sizeof(size));
            bid.resize(size);
            ask.resize(size);
            in.read(reinterpret_cast<char*>(bid.data()), size * sizeof(double));
            in.read(reinterpret_cast<char*>(ask.data()), size * sizeof(double));
    
            size_t close_size;
            in.read(reinterpret_cast<char*>(&close_size), sizeof(close_size));
            close_prices.resize(close_size);
            in.read(reinterpret_cast<char*>(close_prices.data()), close_size * sizeof(double));
    
            size_t tick_size;
            in.read(reinterpret_cast<char*>(&tick_size), sizeof(tick_size));
            tick_numbers.resize(tick_size);
            in.read(reinterpret_cast<char*>(tick_numbers.data()), tick_size * sizeof(int));
    
        }
        catch (const std::exception& e) {
            std::cerr << "Exception while reading compressed data: " << e.what() << std::endl;
        }
    }

我测试了这个,但是 uint64_t size = bid.size();读取坏字节..可能是什么原因?

c++ boost
1个回答
0
投票

我无法重现这一点。我建议概括代码,以便您可以更直接地编写它:

using Amount  = double;
using Amounts = std::vector<Amount>;
using Tick    = int;
using Ticks   = std::vector<Tick>;

struct Data {
    Amounts bid, ask, close_prices;
    Ticks   tick_numbers;

    auto operator<=>(Data const&) const = default;

    void save(std::ostream& os) const {
        assert(ask.size() == bid.size());
        WriteRaw(                              //
            os, bid.size(), bid, ask,          //
            close_prices.size(), close_prices, //
            tick_numbers.size(), tick_numbers  //
        );                                     //
    }

    void load(std::istream& is) {
        auto n = ReadVector(is, bid);
        ReadVector(is, ask, n);
        ReadVector(is, close_prices);
        ReadVector(is, tick_numbers);
    }
};

void saveCompressedData(std::string const& file_path, Data const& data) try {
    std::ofstream         file(file_path, std::ios::binary);
    io::filtering_ostream out;
    out.push(io::gzip_compressor{});
    out.push(file);

    data.save(out);
} catch (std::exception const& e) {
    std::cerr << "Exception while writing compressed data: " << e.what() << std::endl;
}

void loadCompressedData(std::string const& file_path, Data& data) try {
    std::ifstream         file(file_path, std::ios::binary);
    io::filtering_istream in;
    in.push(io::gzip_decompressor{});
    in.push(file);

    data.load(in);
} catch (std::exception const& e) {
    std::cerr << "Exception while reading compressed data: " << e.what() << std::endl;
}

读/写助手使用字节跨度来避免编程错误。

namespace /* filestatic */ {
    void WriteRaw(std::ostream& os, std::span<std::byte const> v);
    void ReadRaw(std::istream& is, std::span<std::byte> v);

    // write helpers
    template <typename T> void    WriteRaw(std::ostream& os, std::vector<T> const& v);
    template <typename T> void    WriteRaw(std::ostream& os, T const& v);
    template <typename... T> void WriteRaw(std::ostream& os, T const&... vs);

    // read helpers
    template <typename T> void    ReadRaw(std::istream& is, T& v);
    template <typename... T> void ReadRaw(std::istream& is, T&... vs);

    template <typename T> void   ReadVector(std::istream& is, std::vector<T>& v, size_t size);
    template <typename T> size_t ReadVector(std::istream& is, std::vector<T>& v);
} // namespace

实现还应确保元素值是可按位复制的。

完整演示

住在Coliru

#include <boost/iostreams/filter/gzip.hpp>
#include <boost/iostreams/filtering_stream.hpp>
#include <fstream>
#include <iostream>
#include <span>

namespace io = boost::iostreams;

namespace /* filestatic */ {
    void WriteRaw(std::ostream& os, std::span<std::byte const> v) {
        os.write(reinterpret_cast<char const*>(v.data()), v.size());
    }
    void ReadRaw(std::istream& is, std::span<std::byte> v) {
        is.read(reinterpret_cast<char*>(v.data()), v.size());
    }

    // write helpers
    template <typename T> void WriteRaw(std::ostream& os, std::vector<T> const& v) {
        static_assert(std::is_trivially_copyable_v<T>);
        WriteRaw(os, std::as_bytes(std::span(v)));
    }
    template <typename T> void WriteRaw(std::ostream& os, T const& v) {
        static_assert(std::is_trivially_copyable_v<T>);
        WriteRaw(os, std::as_bytes(std::span(&v, 1)));
    }
    template <typename... T> void WriteRaw(std::ostream& os, T const&... vs) {
        (WriteRaw(os, vs), ...);
    }

    // read helpers
    template <typename T> void ReadRaw(std::istream& is, T& v) {
        static_assert(std::is_trivially_copyable_v<T>);
        ReadRaw(is, std::as_writable_bytes(std::span(&v, 1)));
    }
    template <typename... T> void ReadRaw(std::istream& is, T&... vs) {
        (ReadRaw(is, vs), ...);
    }

    template <typename T> void ReadVector(std::istream& is, std::vector<T>& v, size_t size) {
        static_assert(std::is_trivially_copyable_v<T>);
        v.resize(size);
        ReadRaw(is, std::as_writable_bytes(std::span(v)));
    }
    template <typename T> size_t ReadVector(std::istream& is, std::vector<T>& v) {
        static_assert(std::is_trivially_copyable_v<T>);
        size_t tmpsize;
        ReadRaw(is, tmpsize);
        ReadVector(is, v, tmpsize);
        return tmpsize;
    }
}

using Amount  = double;
using Amounts = std::vector<Amount>;
using Tick    = int;
using Ticks   = std::vector<Tick>;

struct Data {
    Amounts bid, ask, close_prices;
    Ticks   tick_numbers;

    auto operator<=>(Data const&) const = default;

    void save(std::ostream& os) const {
        assert(ask.size() == bid.size());
        WriteRaw(                              //
            os, bid.size(), bid, ask,          //
            close_prices.size(), close_prices, //
            tick_numbers.size(), tick_numbers  //
        );                                     //
    }

    void load(std::istream& is) {
        auto n = ReadVector(is, bid);
        ReadVector(is, ask, n);
        ReadVector(is, close_prices);
        ReadVector(is, tick_numbers);
    }
};

void saveCompressedData(std::string const& file_path, Data const& data) try {
    std::ofstream         file(file_path, std::ios::binary);
    io::filtering_ostream out;
    out.push(io::gzip_compressor{});
    out.push(file);

    data.save(out);
} catch (std::exception const& e) {
    std::cerr << "Exception while writing compressed data: " << e.what() << std::endl;
}

void loadCompressedData(std::string const& file_path, Data& data) try {
    std::ifstream         file(file_path, std::ios::binary);
    io::filtering_istream in;
    in.push(io::gzip_decompressor{});
    in.push(file);

    data.load(in);
} catch (std::exception const& e) {
    std::cerr << "Exception while reading compressed data: " << e.what() << std::endl;
}

#include <fmt/ranges.h>
int main() {
    using L = std::numeric_limits<Amount>;
    for (Data const& data : {
             Data{{1.0, 2.0, 3.0}, {4.0, 5.0, 6.0}, {7.0, 8.0, 9.0}, {10, 11, 12}},
             Data{{1.1111e11, 2.2222e11, 3.3333e11, 4.4444e11},
                  {5.5555e11, 6.6666e11, 7.7777e11, 8.8888e11},
                  {7.7777e11},
                  {10, 11, 12, 13, 14}},
             Data{{}, {}, {0.10, L::infinity(), -L::infinity(), 10.2, 10.3, 10.4}, {}},
             Data{},
             // nan is always "not equal" to itself, but also roundtrips
             Data{{}, {}, {L::quiet_NaN()}, {}},
         }) {
        saveCompressedData("test.gz", data);

        Data roundtrip;
        loadCompressedData("test.gz", roundtrip);

        auto& [bid, ask, close_prices, tick_numbers] = roundtrip;
        fmt::print ("bid: {}\nask: {}\nclose_prices: {}\ntick_numbers: {}\n", bid, ask, close_prices, tick_numbers);
        std::cout << "Roundtrip: " << (data == roundtrip ? "OK" : "FAIL") << "\n---------------\n" << std::endl;
    }
}

打印

bid: [1, 2, 3]
ask: [4, 5, 6]
close_prices: [7, 8, 9]
tick_numbers: [10, 11, 12]
Roundtrip: OK
---------------

bid: [111110000000, 222220000000, 333330000000, 444440000000]
ask: [555550000000, 666660000000, 777770000000, 888880000000]
close_prices: [777770000000]
tick_numbers: [10, 11, 12, 13, 14]
Roundtrip: OK
---------------

bid: []
ask: []
close_prices: [0.1, inf, -inf, 10.2, 10.3, 10.4]
tick_numbers: []
Roundtrip: OK
---------------

bid: []
ask: []
close_prices: []
tick_numbers: []
Roundtrip: OK
---------------

bid: []
ask: []
close_prices: [nan]
tick_numbers: []
Roundtrip: FAIL
---------------
© www.soinside.com 2019 - 2024. All rights reserved.