Как я могу писать "один бит" в поток файлов или файловую структуру каждый раз? можно ли записать в очередь, а затем сбросить его? возможно ли с С# или java? это было необходимо, когда я пытаюсь реализовать экземпляр Huffman codding. Я не могу записать бит в файлы. поэтому записывайте их в битовый набор, а затем (когда сжатие завершено) каждый раз записывайте 8-битный фрагмент (исключая последний).
Запись "бит" в потоки файлов С++
Ответ 1
Буферизация отдельных битов, пока вы не накопили целый байт, не кажется хорошей идеей:
byte b;
int s;
void WriteBit(bool x)
{
b |= (x ? 1 : 0) << s;
s++;
if (s == 8)
{
WriteByte(b);
b = 0;
s = 0;
}
}
Вам просто нужно иметь дело с случаем, когда количество бит, которое должно быть записано, не кратно восьми.
Ответ 2
Вы можете использовать boost::dynamic_bitset
вместе с std::ostream_iterator
для достижения желаемого результата в сжатом виде:
#include <fstream>
#include <iterator>
#include <boost/dynamic_bitset.hpp>
typedef boost::dynamic_bitset<unsigned char> Bitset;
// To help populate the bitset with literals */
Bitset& operator<<(Bitset& lhs, bool val) {lhs.push_back(val); return lhs;}
int main()
{
Bitset bitset;
bitset<<0<<1<<0<<1<<0<<1<<0<<1
<<1<<0<<1<<0;
std::ofstream os("data.dat", std::ios::binary);
std::ostream_iterator<char> osit(os);
boost::to_block_range(bitset, osit);
return 0;
}
Я сделал размер блока моих dynamic_bitset
8 бит, указав unsigned char
в качестве параметра шаблона. Размер блока можно увеличить, указав более крупный целочисленный тип.
boost::to_block_range
сбрасывает бит в блоках с заданным выходным итератором. Если в последнем блоке есть пустые остаточные бит, они будут заполнены нулем.
Когда я открываю data.dat в шестнадцатеричном редакторе, я вижу: AA 05
. Это находится на маленькой платформе endist (x64).
Ответ 3
Какую файловую систему вы используете?
Скорее всего, он хранит длину файла в байтах (есть ли какие-то нет?), поэтому невозможно иметь физический файл, который не является целым числом байтов.
Итак, если вы пишете файл в виде потока бит, вам нужно либо урезать последние несколько бит, когда вы закончите, либо выписать окончательный байт с помощью каких-то сбоев в оставшихся битах.
Здесь приведен код Python, чтобы начать работу
class BitFile(file):
def __init__(self, filename, mode):
super(BitFile, self).__init__(filename, mode)
self.bitCount=0
self.byte = 0
def write(self, bit):
self.bitCount+=1
self.byte = self.byte*2+bit
if self.bitCount%8==0:
super(BitFile, self).write(chr(self.byte))
self.byte=0
def close(self):
if self.bitCount%8!=0:
super(BitFile, self).write(chr(self.byte))
super(BitFile, self).close()
with BitFile("bitfile.bin","w") as bf:
bf.write(1)
bf.write(1)
bf.write(1)
bf.write(0)
bf.write(0)
bf.write(0)
bf.write(0)
bf.write(0)
bf.write(1)
Ответ 4
Ты не можешь. Я уверен, что проблема связана не с языком или файловой системой, а с аппаратной проблемой. Процессоры предназначены для работы с байтами. Вероятно, самое близкое, что вы можете сделать, - это писать свой последний байт снова и снова, правильно дополняясь нулями, меняя их по ходу, по одному за раз.
поэтому для записи битов "11011" вы можете сделать следующее (пример python, но любой язык должен иметь возможности для этого:
f.write(chr(0b10000000))
f.flush()
f.seek(-1)
f.write(chr(0b11000000))
f.flush()
f.seek(-1)
f.write(chr(0b11000000))
f.flush()
f.seek(-1)
f.write(chr(0b11010000))
f.flush()
f.seek(-1)
f.write(chr(0b11011000))
f.flush()
Вы не надеялись получить какую-то выгоду от этого, не так ли?
Ответ 5
Я бы рекомендовал выделить довольно большой буфер (по меньшей мере, 4096 байт) и сбросить его на диск всякий раз, когда он заполняется. Использование однобайтового буфера обычно приводит к плохой производительности.
Ответ 6
Я сделал это один раз для декодирования хаффмана и закончил писать биты в виде символов и, таким образом, обрабатывал все внутри себя как обычную старую строку C.
Таким образом, вам не нужно беспокоиться о завершающем байте, и это также понятно для человека. Кроме того, проверка битов проще, поскольку он просто предназначен для адресации массива char (binbuf[123] == '1'
) вместо того, чтобы играть с битами. Не самое оптимизированное решение, но оно решило мою проблему аккуратно.
Очевидным недостатком является то, что это представление использует больше памяти.
Ответ 7
Проблема в том, что многие платформы не имеют прямого доступа к битам. Они группируют биты в минимальный пакет, часто с байтом или словом. Кроме того, протокол для потоковых устройств не облегчает передачу отдельных битов.
Общим методом обработки отдельных битов является их упаковка в самый маленький портативный и (адресуемый) доступный модуль. Неиспользуемые биты обычно устанавливаются на ноль. Это может быть выполнено с помощью двоичных арифметических операций (OR, AND, EXCLUSIVE-OR, NOT и т.д.).
С современными процессорами бит-скручивание замедляет работу машины и производительность. Память дешевая и с большими адресными пространствами, обоснование для упаковки битов стало более сложным. Как правило, бит-упаковка зарезервирована для аппаратно-ориентированных операций (а также протоколов передачи). Например, если емкость процессора составляет 16 бит, процессор, вероятно, может обрабатывать 16 слов быстрее, чем 16-битные манипуляции одним словом.
Кроме того, имейте в виду, что запись в и из памяти часто быстрее, чем ввод-вывод из потоков. Эффективные данные буфера системы в памяти перед передачей данных. Вы можете рассмотреть эту технику в своих проектах. Сокращение операций ввода-вывода улучшит производительность вашей программы.