我有一个文件,其中包含非字节对齐的数据,我想在文件中寻找(例如3位),然后开始将字符读入缓冲区。有没有"容易"这样做的方法?
我希望尽可能避免在缓冲区中对每个字符进行位移。
答案 0 :(得分:3)
除非您使用的是非常有趣的平台,否则您的文件包含字节。你一次读一个字节。所以如果没有位移,就没有办法做到这一点。 隐藏我想到的位移的最简单方法是创建一个输入迭代器,用于存储先前读取的字节并在“幕后”进行移位。
答案 1 :(得分:0)
std::ifstream专门用于charT to char,这是标准提供的最小数据块。我知道在位级访问文件没有标准的低级方法。您必须至少阅读文件的一部分并在代码中进行分析。
你在google上找到了一些std :: stream适配器,这些适配器允许一点一点地阅读,但我不确定你是否真的需要它。我找到的就是:http://stanford.edu/~stepp/cppdoc/ibitstream-class.html
[编辑]
下面是一个读取此类文件的示例,其中使用带有位域的struct:
#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 :(得分:0)
这是一个非常简单的bit_iterator,它包装了一个forward_only istream迭代器。它允许将单个位提取为单词。
这足以让你朝着正确的方向前进。
#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