2010-06-12 238 views
3

所以我想解析一個二進制文件並從中提取一些數據。我面臨的問題是我需要將一串char s轉換爲一串unsigned char s。 閱讀Boost文檔,似乎boost::iostreams::code_converter應該是這樣的解決方案,所以我嘗試這樣做:使用boost :: iostreams逐字節解析二進制文件

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; 

當時的想法是指定與InternalType=uint8_tExternalType=char一個codecvt。不幸的是,這不能編譯。 所以問題是:如何將char s的流轉換爲uint8_t s的流?

回答

2

我不知道你是否仍然有這個問題,但如果你這樣做,你能否詳細說明你到底想達到什麼目的。內部char和unsigned char是相同的。他們只有8位坐在某個地方。不需要轉換。

唯一的區別是編譯器在使用它們時如何解釋它們。這意味着您應該能夠在使用時通過使用static_cast來解決大多數問題。

對於您的信息,std :: cout將輸出一個與char相同的無符號字符。如果你想要的數值,你必須投兩次:

array_stream s; //initialized properly in the code 
unsigned char asd; 
s >> asd; 

std:cout << int(asd); 

我可以看到在此不便和可能的boost ::輸入輸出流有一定的方法來爲你做的,但我從來沒有使用升壓:: iostreams並在這裏查看答案的數量,沒有多少人可以幫助你。如果一切都失敗了,只需重新解釋數據即可。在任何情況下,如果這意味着全部複製,那麼轉換它是一個糟糕的主意。

+0

所以我想原題的大局觀是,我想給的boost ::精神的無符號流字符解析。因此,每當我嘗試從流中讀取某些內容時都無法使用靜態代碼(不是我的代碼正在完成所有的閱讀)。 我最終通過廢除boost :: iostreams並使用spirit中基於迭代器的解析器來解決這個問題。 – Zsol 2010-08-28 16:15:36

1

你可以編寫處理uint8_t &朋友的自定義設備。這裏有一個例子:

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;