连接二进制位大小的字符串

时间:2014-09-06 07:35:59

标签: c++ bit-manipulation bit

我想在文件中写入一系列二进制字符串,其长度以位而不是字节表示。考虑两个字符串 s1 s2 ,它们分别是011和01011.在这种情况下,输出文件的内容必须是:01101011(1字节)。我试图以最有效的方式做到这一点,因为我有几百万个字符串连接在输出中总共几GB。

3 个答案:

答案 0 :(得分:1)

没有最佳方法可以解决您的问题。但是你可以用几个捏来加快速度:

  1. 试用文件I / O同步标志。由于缓冲和缓存,set / unset可能比另一个快得多。
  2. 尝试使用体系结构大小的变量,使它们直接适合寄存器:32位机器的uint32_t和64位机器的uint64_t ......
  3. "挥发性"可能会有所帮助,将事情记录在寄存器中
  4. 使用大数据的指针和引用并复制小数据blob(以避免不必要的大数据副本以及大量数据的查找和页面触摸)
  5. 使用文件的mmap进行直接访问,并将输出与架构和硬盘的页面大小对齐(通常为4 KiB = 4096 Bytes)
  6. 尝试减少分支(如#34;如果","","","()?:")并线性化您的代码。
  7. 如果这还不够,当事情变得粗糙:使用汇编程序(但我不建议初学者)
  8. 我认为多线程在这种情况下会产生相反的效果,因为可以发出有限的文件写入,并且问题不容易分成小任务,因为每个人都需要知道其他人之后有多少位开始然后你必须最后将所有结果加在一起。

答案 1 :(得分:1)

我过去使用过以下内容,可能会有所帮助...

<强> FileWriter.h:

#ifndef FILE_WRITER_H
#define FILE_WRITER_H

#include <stdio.h>

class FileWriter
{
public:
    FileWriter(const char* pFileName);
    virtual ~FileWriter();
    void AddBit(int iBit);
private:
    FILE* m_pFile;
    unsigned char m_iBitSeq;
    unsigned char m_iBitSeqLen;
};

#endif

<强> FileWriter.cpp:

#include "FileWriter.h"
#include <limits.h>

FileWriter::FileWriter(const char* pFileName)
{
    m_pFile = fopen(pFileName,"wb");
    m_iBitSeq = 0;
    m_iBitSeqLen = 0;
}

FileWriter::~FileWriter()
{
    while (m_iBitSeqLen > 0)
        AddBit(0);
    fclose(m_pFile);
}

void FileWriter::AddBit(int iBit)
{
    m_iBitSeq |= iBit<<CHAR_BIT;
    m_iBitSeq >>= 1;
    m_iBitSeqLen++;
    if (m_iBitSeqLen == CHAR_BIT)
    {
        fwrite(&m_iBitSeq,1,1,m_pFile);
        m_iBitSeqLen = 0;
    }
}

您可以在将数据写入文件之前将数据累积到一定数量,从而进一步改进。

答案 2 :(得分:1)

C ++没有办法直接使用位,因为它的目标是成为一个轻薄层 在硬件之上,硬件本身不是面向位的。最低限度 在一次操作中可以读/写的位数是一个字节(通常是8位)。

此外,如果您需要执行磁盘i / o,最好以块为单位而不是一次一个字节来写入数据。该库有一些缓冲,但早期的事情被缓冲,代码将越快(传递数据所涉及的代码越少)。

一种简单的方法可能是

unsigned char iobuffer[4096];
int bufsz; // how many bytes are present in the buffer

unsigned long long bit_accumulator;
int acc_bits; // how many bits are present in the accumulator

void writeCode(unsigned long long code, int bits) {
    bit_accumulator |= code << acc_bits;
    acc_bits += bits;
    while (acc_bits >= 8) {
        iobuffer[bufsz++] = bit_accumulator & 255;
        bit_accumulator >>= 8;
        acc_bits -= 8;
        if (bufsz == sizeof(iobuffer)) {
            // Write the buffer to disk
            bufsz = 0;
        }
    }
}