所以我想解析一个二进制文件并从中提取一些数据。我面临的问题是我需要将char
的流转换为unsigned char
的流。
阅读boost文档,似乎boost::iostreams::code_converter
应该是解决方案,所以我尝试了这个:
typedef unsigned char uint8_t;
typedef boost::iostreams::stream<boost::iostreams::code_converter<
boost::iostreams::basic_array_source<uint8_t>,
std::codecvt<uint8_t, char, std::mbstate_t> > > array_stream;
array_stream s; //initialized properly in the code
unsigned char asd;
s >> asd;
std::cout << asd << std::endl;
我们的想法是使用codecvt
和InternalType=uint8_t
指定ExternalType=char
。不幸的是,这不编译。
问题是:如何将char
的流转换为uint8_t
的流?
答案 0 :(得分:2)
我不知道你是否还有这个问题,但是如果你这样做,你能否详细说明你想要达到的目标。事物是内部char和unsigned char是相同的。它们只有8位坐在某处。无需转换。
唯一的区别在于编译器在使用它们时如何解释它们。这意味着您应该能够在使用时使用static_cast来解决大多数问题。
顺便提一下,std :: cout会输出一个与char相同的unsigned char。如果你想要数值,你必须将它投两次:
array_stream s; //initialized properly in the code
unsigned char asd;
s >> asd;
std:cout << int( asd );
我可以看到这方面带来的不便,可能还有提升:: iostreams有一些方法可以帮到你,但是我从来没有使用过boost :: iostreams,看看这里的答案数量,没有多少可以帮到你。如果所有其他方法都失败了,只需重新解释数据即可。在任何情况下转换它都是一个坏主意,如果这意味着复制它。
答案 1 :(得分:1)
您可以编写处理uint8_t
&amp;的自定义设备。朋友。这是一个例子:
template <typename Container>
class raw_back_insert_device
{
public:
typedef char char_type;
typedef typename Container::value_type raw_char_type;
typedef boost::iostreams::sink_tag category;
raw_back_insert_device(Container& container)
: container_(container)
{
}
std::streamsize write(char const* s, std::streamsize n)
{
auto start = reinterpret_cast<raw_char_type const*>(s);
container_.insert(container_.end(), start, start + n);
return n;
}
private:
Container& container_;
};
template <typename Container>
raw_back_insert_device<Container> raw_back_inserter(Container& cnt)
{
return raw_back_insert_device<Container>(cnt);
}
class raw_array_source : public boost::iostreams::array_source
{
public:
template <typename Char>
raw_array_source(Char const* begin, Char const* end)
: boost::iostreams::array_source(
reinterpret_cast<char const*>(begin),
reinterpret_cast<char const*>(end))
{
}
template <typename Char>
raw_array_source(Char const* begin, size_t size)
: boost::iostreams::array_source(
reinterpret_cast<char const*>(begin),
size)
{
}
template <typename Container>
raw_array_source(Container& container)
: raw_array_source(container.data(), container.size())
{
}
std::streamsize read(char* s, std::streamsize n)
{
auto i = input_sequence();
auto min = std::min(i.second - i.first, n);
std::copy(i.first, i.first + min, s);
return min;
}
};
template <typename Container>
raw_array_source raw_container_source(Container& container)
{
return raw_array_source(container);
}
您可以看起来如下:
typedef unsigned char uint8_t;
typedef boost::iostreams::stream<
boost::iostreams::code_converter<
raw_array_source,
std::codecvt<uint8_t, char, std::mbstate_t>
>
> array_stream;
array_stream s; //initialized properly in the code
unsigned char asd;
s >> asd;
std::cout << asd << std::endl;