从平台上的文件读取字符,其中字节> 8位

时间:2016-04-08 19:30:41

标签: c++

如果我有一个包含以下数据的二进制文件(写在1字节== 8位的平台上):0x01, 0x10, 0x20, 0x40, 0xff

following program是否可移植到platform where 1 byte != 8 bits

#include <iterator>
#include <fstream>

int main()
{
    std::fstream file("binaryfile");
    std::istreambuf_iterator<char> iter{file}, end;
    for (; iter != end; ++iter) {
        char c{*iter};
    }
}

换句话说;如果读取平台有一个16位到一个字节,它会读取2个字节吗?

1 个答案:

答案 0 :(得分:-1)

大多数程序可能都不便携

阅读评论here,我认为答案是该程序并非按照C ++标准完全可移植。没有节目。 编辑:至少没有与网络通信,读取或写入磁盘或希望其他平台应答或更新数据的程序。

C ++支持平台的硬件,而不是Java。例如,fgetcfputc是保持往返值,但仅限于同一平台。网络消息有效,因为每个人都假设一个字节为8位。

如果有问题,那么最好断言平台有8位到一个字节:static_assert(CHAR_BIT==8, "Platform must have 8 bits to a byte.");

即使没有断言,也会有其他警钟。一个平台没有8位到一个字节,但仍然通过网络或文件与其他平台通信将比以后更早失败并将代码移植到它将需要额外的工作来使用假定的8位读取和写入数据事实上的标准。这看起来很像字节序问题,但这里的区别在于一方非常明显地赢了。

但它们可以随身携带

编辑:上面的陈述可能并不总是成立。通过适当的努力,该程序可以变得便携。 Mooing Duck的以下改编演示了该程序和迭代器如何考虑如何使用不同的位数进行操作。它显示了具有更多位的系统如何从具有较少位的系统读取文件。这可以扩展到双向工作:

#include <iterator>
#include <climits>
#include <iostream>

template<class base_iterator, size_t source_bits>
class bititerator : public std::iterator<std::input_iterator_tag, unsigned char> {
    mutable base_iterator base;
    mutable unsigned char bufferhi;
    mutable unsigned char bufferlo;
    mutable unsigned char bitc;
public:
    bititerator(const base_iterator& b) : base(b), bufferhi(0), bufferlo(0), bitc(0) {}
    bititerator& operator=(const bititerator&b) {base = b.base; bufferlo=b.bufferlo; bufferhi=b.bufferhi; bitc=b.bitc; return *this;}
    friend void swap(bititerator&lhs, bititerator&rhs) {std::swap(lhs.base, rhs.base); std::swap(lhs.bufferlo, rhs.bufferlo); std::swap(lhs.bufferhi, rhs.bufferhi); std::swap(lhs.bit, rhs.bitc);}
    bititerator operator++(int) {bititerator t(*this); ++*this; return t;}
    unsigned char* operator->() const {operator*(); return &bufferlo;}
    friend bool operator==(const bititerator&lhs, const bititerator&rhs) {return lhs.base==rhs.base && lhs.bitc==rhs.bitc;}
    friend bool operator!=(const bititerator&lhs, const bititerator&rhs) {return !(lhs==rhs);}
    unsigned char operator*() const {
        static_assert(source_bits<CHAR_BIT, "bititerator only works on systems with more bits than the target");
        //make sure at least source_bits bits are in the buffers
        if (bitc < source_bits) {
            bufferhi = static_cast<unsigned char>(*base);
            ++base;
            size_t shift = source_bits-bitc;
            bufferlo |= ((bufferhi<<shift)&0xFF);
            bufferhi >>= shift;
            bitc += CHAR_BIT;
        }
        return bufferlo;

    }
    bititerator& operator++() {
        operator*();
        //shift the buffers down source_bits bits
        bufferlo >>= source_bits;
        bufferlo |= ((bufferhi<<(CHAR_BIT-source_bits))&0xFF);;
        bufferhi >>= source_bits;
        bitc -= source_bits;
        return *this;
    }
};

template<class base_iterator>
bititerator<base_iterator,6> from6bit(base_iterator it) {return bititerator<base_iterator,6>(it);}
bititerator<std::istreambuf_iterator<char>,6> from6bitStart(std::istream& str) {return bititerator<std::istreambuf_iterator<char>,6>{std::istreambuf_iterator<char>{str}};}
bititerator<std::istreambuf_iterator<char>,6> from6bitEnd(std::istream& str) {return bititerator<std::istreambuf_iterator<char>,6>{std::istreambuf_iterator<char>{}};}

#include <fstream>
int main()
{
    std::fstream file("binaryfile");
    auto end = from6bitEnd(file);
    for (auto iter = from6bitStart(file); iter != end; ++iter)
        std::cout << *iter;
}