2016-04-05 3 views
3

バイト整列されていないデータを含むファイルがあり、そのファイルにシーク(3ビットなど)してから、バッファに読み込みを開始したい。これを行うための「簡単な」方法はありますか?ファイルにn個のビットをシークする(C++)

可能であれば、バッファ内の各文字をビットシフトしないようにします。

+0

"バイト整列されていないデータ" どのようにそれは可能ですか? – Pierre

+2

あなたは、あなたが注意していることを避けるつもりはありません。どちらかといえば、シフトやマスキングがメニューにあります。 – WhozCraig

+0

ハードウェアの製造元に相談する必要があります。 – Ajay

答えて

3

非常に興味深いプラットフォームを使用していない限り、ファイルにはバイトが含まれています。そしてあなたはそれを一度に1バイト読む。したがって、ビットシフトなしでそれを行う方法はありません。最も簡単な方法は、私が考えることができるビットシフトを非表示にするには、以前に読み込まれたバイトを格納し、シフト "バックシーン"を入力イテレータを作ることです。

+0

これが答えです。私は誰かがちょっとしたハックを知ってくれることを願っていました。 Richard HodgesとMarcinJędrzejewskiに感謝します。 – user102569

0

std::ifstreamはcharTをcharに特化しており、標準で提供されるデータの最小チャンクです。ビットレベルのファイルにアクセスするための標準的な低レベルの方法はありません。ファイルの少なくとも一部を読んで、分析をコードで行う必要があります。

あなたはgoogleで少しずつ読むことができるいくつかのstd :: streamアダプタがありますが、本当に必要かどうかはわかりません。私が見つけた一つがここにある:http://stanford.edu/~stepp/cppdoc/ibitstream-class.html

[編集]

以下はビットフィールドを持つ構造体を使用して、このようなファイルを読み込むサンプルです:

liveここ

#include <iostream> 
#include <fstream> 
#include <cassert> 
#include <vector> 

int main() 
{ 
    // Write test data 
    std::vector<bool> bit; 
    bit.push_back(0); 
    bit.push_back(0); 
    bit.push_back(0); 

    // Write test byte data, it is padded by 3 bits in front 
    for (int n = 0; n < 80 * 13; ++n) 
     bit.push_back((n/8 % 2)==0); 

    std::ofstream ofs("test.data", std::ifstream::binary); 
    for (auto it = bit.begin(); it != bit.end();) { 
     char toWrite = 0; 
     for (int n = 7; it!=bit.end() && n >= 0; --n, ++it) toWrite |= *it << n; 
     ofs.write(&toWrite, 1); 
    } 
    ofs.close(); 

    // Read data 
    union S { 
     struct { 
      unsigned short pad : 5; 
      unsigned short dat : 8; 
      unsigned short oth : 3; 
     } inner; 
     char bytes[2]; 
    } data; 

    // Create bit vector to verify if reading is correct. 
    std::vector<bool> bit2; 
    bit2.push_back(0); // First three bits are padding 
    bit2.push_back(0); 
    bit2.push_back(0); 

    std::ifstream ifs("test.data", std::ifstream::binary); 
    while(ifs.read(data.bytes, sizeof(data.bytes))) { 
     std::swap(data.bytes[0], data.bytes[1]); 
     // std::cout << data.inner.dat << ", "; 
     for (int n = 7; n >= 0; --n) bit2.push_back(data.inner.dat & (1 << n)); 
     ifs.seekg(-1, ifs.cur); 
    } 
    assert(bit == bit2); 
} 
+2

私は信じて、この構造体は2バイトのサイズを持っています。ポスターはバイト単位でデータを読み込みたいのですが、最初のバイトの3番目のビットから開始します。 – grisumbras

+0

@グリムブラブあなたが正しいです、私はその部分を削除しました – marcinj

0

は非常に単純ですforward_only istreamイテレータをラップするbit_iterator。個々のビットを単語に抽出することができます。

正しい方向に動くのに十分なはずです。

#include <iostream> 
#include <iterator> 
#include <iomanip> 
#include <sstream> 

// forward-only iterator for simplicity 
template<class Iter> 
struct bit_iterator 
{ 
    using word_type = typename Iter::value_type; 
    static constexpr int end_bit = sizeof(word_type) * 8; 

    bit_iterator(Iter underlying) : _iter(underlying) {}; 

    word_type operator*() { 
     if (_bitnum == end_bit) 
     { 
      _word = *_iter++; 
      _bitnum = 0; 
     } 
     auto ret = (_word & (1 << _bitnum++)) ? 1 : 0; 
     return ret; 
    } 

    bit_iterator& operator++() { 
     return *this; 
    } 

    bit_iterator& operator++(int) { 
     return *this; 
    } 

    Iter underlying() const { 
     return _iter; 
    } 

    Iter _iter; 
    word_type _word; 
    int _bitnum = end_bit; 
}; 

template<class Iter> 
auto make_bit_iterator(Iter iter) 
{ 
    return bit_iterator<Iter>(iter); 
} 

template<class Word, class Iter> 
Word get_bits(Iter& iter, size_t bits = sizeof(Word) * 8) 
{ 
    Word acc = 0; 
    for (; bits ; --bits) 
    { 
     acc = (acc << 1) | *iter++; 
    } 
    return acc; 
} 

int main(int argc, char * argv[]) 
{ 
    std::istringstream is("abcdefghijklmnop"); 

    auto i = make_bit_iterator(std::istream_iterator<char>(is)); 

    auto first_three = get_bits<char>(i, 3); 

    std::cout << std::hex << int(get_bits<std::uint8_t>(i)) << std::endl; 
    std::cout << std::hex << get_bits<std::int32_t>(i) << std::endl; 
    std::cout << std::hex << get_bits<std::uint16_t>(i) << std::endl; 

    return 0; 
} 

期待される結果:

32 
36313533 
3730 
関連する問題