2010-06-12 5 views
3

Je voudrais donc analyser un fichier binaire et en extraire des données. Le problème que je suis confronté à cela est que j'ai besoin de convertir un flux de char à un flux de unsigned char s. lecture de la documentation boost, il semble que boost::iostreams::code_converter devrait être la solution pour cela, donc j'ai essayé ceci:Utiliser boost :: iostreams pour analyser un octet par octet de fichier binaire

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; 

L'idée était de spécifier un codecvt avec InternalType=uint8_t et ExternalType=char. Malheureusement, cela ne compile pas. Donc la question est: comment puis-je convertir un flux de char à un flux de uint8_t s?

Répondre

2

Je ne sais pas si vous avez toujours ce problème, mais si vous le faites, pourriez-vous nous en dire un peu plus sur ce que vous essayez de faire exactement. La chose est en interne char et unsigned char sont les mêmes. Ils sont juste 8 bits assis quelque part. Aucune conversion n'est nécessaire. La seule différence réside dans la façon dont le compilateur les interprète lorsque vous les utilisez. Cela signifie que vous devriez être capable de résoudre la plupart des problèmes en utilisant static_cast au moment de l'utilisation. Pour votre information, std :: cout affichera un caractère non signé identique à un caractère. Si vous voulez que la valeur numérique que vous devez jeter deux fois:

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

std:cout << int(asd); 

je peux voir l'inconvénient dans ce domaine et peut-être boost :: iostreams a une certaine façon de le faire pour vous, mais je n'ai jamais utilisé boost :: iostreams et en regardant le nombre de réponses ici, pas beaucoup peuvent vous aider. Si tout le reste échoue, réinterprétez simplement les données. En tout cas, la conversion serait une mauvaise idée si cela signifiait copier tout cela.

+0

donc je suppose que l'image plus grande de la question initiale était que je voulais donner boost :: esprit un flux de non signé caractères à analyser. Mettre des static_casts partout dans le code chaque fois que j'essaie de lire quelque chose hors du flux n'est pas viable (mon code ne fait pas toute la lecture). J'ai finalement travaillé sur le problème en supprimant boost :: iostreams et en utilisant simplement les parseurs basés sur l'itérateur de l'esprit. – Zsol

1

Vous pouvez écrire des périphériques personnalisés prenant en charge uint8_t & amis. Voici un exemple:

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); 
} 

Votre serait alors pourrait se présenter comme suit:

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; 
Questions connexes