2022-05-20 二进制输入输出类(C++)

C语言和C++从不缺少二进制处理方案,甚至C++有类二进制类 bitset。

当我们想直接操作二进制数据到输入输出流,可能性不大,因为流都被封装了,但这不妨碍我们进行更高抽象的封装。

C 和 C++的二进制流操作 read, write,最小颗粒是 char,字节,8 比特。但C语言提供了位操作,我们可以在此基础上进行每个比特的控制,然后将他们再放进流中,当然,流必须最少是8位的,我们只需要在最后一个压入流的比特进行对齐。

具体的实现是封装两个二进制标准输入和输出类,采用全静态成员及静态函数,可以控制最小一个bit的数据。

一般的用法是通过管道,进行输入输出,如果用标准输出,你可能看到的是乱码。

#include 
#include 
#include 
#include 

struct BinaryStdIn
{
    //单例模式,不可实体化
    BinaryStdIn() = delete;
    //比特流是否为空
    static auto isEmpty() -> bool
    {
        return buffer == EOF;
    }
    //读取1位数据并返回一个bool值
    static auto readBool() -> bool
    {
        if (isEmpty())
        {
            throw "Reading form empty input stream";
        }
        N--;
        bool bit = buffer[N];
        if (N == 0)
        {
            fillBuffer();
        }
        return bit;
    }
    //读取8位数据并返回一个char值
    static auto readChar() -> char
    {
        if (isEmpty())
        {
            throw "Reading form empty input stream";
        }
        if (N == 8)
        {
            auto x = buffer;
            fillBuffer();
            return static_cast<char>(x.to_ulong() & 0xff);
        }
        auto x = buffer;
        x <<= (8 - N);
        int oldN = N;
        fillBuffer();
        if (isEmpty())
        {
            throw "Reading form empty input stream";
        }
        N = oldN;
        x |= (buffer >> N);
        return static_cast<char>(x.to_ulong() & 0xff);
    }
    //读取r(1~16)位数据并返回一个char值
    static auto readChar(int r) -> char
    {
        if (r < 1 || r > 16)
        {
            throw std::string("Illegal value of r = ") + std::to_string(r);
        }
        if (r == 8)
        {
            return readChar();
        }
        char x = 0;
        for (int i = 0; i != r; ++i)
        {
            x <<= 1;
            bool bit = readBool();
            if (bit)
            {
                x |= 1;
            }
        }
        return x;
    }
    //关闭比特流
    static void close()
    {
        std::cin.setstate(std::ios::eofbit);
    }
    //静态初始化
    static void begin()
    {
        fillBuffer();
    }

  private:
    //读流到缓冲区
    static void fillBuffer()
    {
        if (std::cin.good())
        {
            std::cin.read(reinterpret_cast<char *>(&buffer), sizeof(char));
            N = 8;
        }
        else
        {
            //    std::cerr << "EOF" << std::endl;
            buffer = EOF;
            N = -1;
        }
    }
    //缓冲区
    static std::bitset<8> buffer;
    //缓冲区比特指针
    static int N;
};

std::bitset<8> BinaryStdIn::buffer;
int BinaryStdIn::N;

struct BinaryStdOut
{
    BinaryStdOut() = delete;
    //刷新缓冲流
    static void flush()
    {
        clearBuffer();
        std::cout.flush();
    }
    //写入指定的比特
    static void write(bool bit)
    {
        writeBit(bit);
    }
    //写入指定的8位字符
    static void write(char c)
    {
        writeByte(c);
    }
    static void write(int x)
    {
        writeByte((x >> 24) & 0xff);
        writeByte((x >> 16) & 0xff);
        writeByte((x >> 8) & 0xff);
        writeByte((x >> 0) & 0xff);
    }
    //写入指定字符的第r(1~16)位
    static void write(char c, int r)
    {
        if (r == 8)
        {
            write(c);
        }
        if (r < 1 || r > 16)
        {
            throw std::string("Illegal value for r = ") + std::to_string(r);
        }
        for (int i = 0; i != r; ++i)
        {
            bool bit = ((c >> (r - i - 1)) & 1) == 1;
            writeBit(bit);
        }
    }
    //关闭比特流
    static void close()
    {
        std::cout.flush();
    }

  private:
    static void writeBit(bool bit)
    {
        buffer <<= 1;
        if (bit)
        {
            buffer |= 1;
        }
        N++;
        if (N == 8)
        {
            clearBuffer();
        }
    }
    static void writeByte(int x)
    {
        assert(x >= 0 && x < 256);
        char c = static_cast<char>(x);
        if (N == 0)
        {
            std::cout.write(&c, sizeof(char));
            return;
        }
        for (int i = 0; i != 8; ++i)
        {
            bool bit = ((c >> (8 - i - 1)) & 1) == 1;
            writeBit(bit);
        }
    }
    static void clearBuffer()
    {
        if (N == 0)
        {
            return;
        }
        if (N > 0)
        {
            buffer <<= (8 - N);
        }
        std::cout.write(reinterpret_cast<char *>(&buffer), sizeof(char));
        N = 0;
        buffer = 0;
    }
    //缓冲区
    static std::bitset<8> buffer;
    //缓冲区比特指针
    static int N;
};

std::bitset<8> BinaryStdOut::buffer;
int BinaryStdOut::N;

void BinaryDump(char *argv[])
{
    BinaryStdIn::begin();
    int width = std::stoi(argv[1]);
    int cnt = 0;
    for (cnt = 0; !BinaryStdIn::isEmpty(); ++cnt)
    {
        if (width == 0)
        {
            continue;
        }
        if (cnt != 0 && cnt % width == 0)
        {
            std::cout << '\n';
        }
        if (BinaryStdIn::readBool())
        {
            std::cout << '1';
        }
        else
        {
            std::cout << '0';
        }
    }
    std::cout << std::endl;
    std::cout << cnt << " bits" << std::endl;
}
auto main(int /*argc*/, char *argv[]) -> int
{
    //   BinaryStdIn::begin();
    //   std::cout << BinaryStdIn::readChar(16) << std::endl;
    //   std::cout << BinaryStdIn::readChar() << std::endl;
    //   std::cout << BinaryStdIn::readBool();
    //   std::cout << BinaryStdIn::readBool();
    //   std::cout << BinaryStdIn::readBool();
    //   std::cout << BinaryStdIn::readBool();
    //   std::cout << BinaryStdIn::readBool();
    //   std::cout << BinaryStdIn::readBool();
    //   std::cout << BinaryStdIn::readBool();
    //   std::cout << BinaryStdIn::readBool();

    BinaryDump(argv);
    //   for (int i = ((48 << 24) + (49 << 16) + (50 << 8) + 51);
    //        i != ((48 << 24) + (49 << 16) + (50 << 8) + 59); ++i)
    //   {
    //       BinaryStdOut::write(i);
    //   }
    //   BinaryStdOut::flush();
    return 0;
}

你可能感兴趣的:(笔记,c++,开发语言,二进制输入输出类)