在文件(C++)中查找n个位数
Seek n number of bits into a file (C++)
我有一个文件,其中包含未按字节对齐的数据,我想在文件中查找(例如3位),然后开始将字符读取到缓冲区中。有没有一种"简单"的方法可以做到这一点?
如果可能的话,我希望避免对缓冲区中的每个字符进行移位。
除非您使用的是一个非常有趣的平台,否则您的文件包含字节。你一次读一个字节。因此,如果不进行比特转换,就没有办法做到这一点。隐藏我能想到的比特移位的最简单方法是制作一个输入迭代器,存储以前读取的字节,并在"后台"进行移位。
这里有一个非常简单的bit_iterator,它封装了一个仅向前的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
std::ifstream专门处理charT到char,这是标准提供的最小数据块。据我所知,在位级别上访问文件没有标准的低级别方式。您必须至少读取文件的一部分,并在代码中进行分析。
你可以在谷歌上找到一些std::stream适配器,它可以一点一点地阅读,但我不确定你是否真的需要这个。我在这里找到了一个:http://stanford.edu/~stepp/cppdoc/iptstream-class.html
[编辑]
以下是使用带位字段的结构读取此类文件的示例:
实时
#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);
}
相关文章:
- 在C++中查找文件
- 在UNIX系统中使用DIR查找文件的字节大小
- 通过搜索硬盘驱动器查找文件目录
- 驱动器号上的查找文件失败,但在路径上传递
- 查找文件中的项目数.txt
- 如何使用c 在Windows中使用更改日记帐查找文件修改
- 如何使用C 在Windows中查找文件是否被修改
- 如何在 c++ 中查找文件指针位置
- 数据文件处理-查找文件中的字数
- 在C 中查找文件的平均薪水
- 比 stat() 在 DIR 中查找文件的更好方法
- C 字符串匹配和使用查找文件替换
- 无法打开或查找文件"afxwin.h",使用.dff(构建毁灭战士3源代码)进行修补
- 如何在不使用目录的情况下在磁盘上查找文件
- 如何避免 CFile查找文件扩展名超过三个字符的误报
- Qt无法在子项目中查找文件
- 查找文件时出现Visual Studio编译错误
- VS2010:设置可执行文件在哪个目录中查找文件
- 使用 C++ 查找文件中的所有重复模式
- 当 seekg 查找文件末尾时未设置故障位 (C++,Linux)