Запись битов в файл в C
У меня есть эта строка: "101"
Я хочу записать его в файл в C, а не как текст: "101" и так 8 бит x char. но напрямую использовать строку в виде битов: бит "1", бит "0" и бит "1", так что файл будет иметь 3 бита.
Возможно ли это?
Я искал в Интернете, и я попытался сделать это:
char c[25] = "101";
FILE *binFile = fopen("binFile.bin", "wb");
int x = atoi(c);
fwrite(&x, sizeof(x), 1, binFile);
Но в конце, когда я проверяю файлы байтов, Windows говорит мне, что это 4-байтовый файл! И не 3bits!
Как я могу это сделать, если это возможно? Большое спасибо.
Ответы
Ответ 1
Все файловые системы¹ обрабатывают файлы в байтах (и выделяют пространство для хранения с гораздо большей детализацией, 512 байт за минимальный минимум). Нет никакого способа получить файл длиной 3 бита.
Лучшее, что вы можете сделать, это использовать один общий байт, но игнорировать 5 его бит. Для этого (при условии, что число всегда будет вписываться в байты), преобразуйте входную строку в интегральный тип:
long l = strtol(c, 0, 2);
Затем получите младший байт:
unsigned char b = l & 0xffl;
И напишите его в файл:
fwrite(&b, 1, 1, binFile);
¹ Ну, может быть, не все. Возможно, некоторые исследователи могут экспериментировать с файловыми системами размером в бит. Я не знаю.
Ответ 2
Ваш выходной файл имеет длину 4 байта, потому что вы пишете файл int
. На большинстве платформ размер int
составляет 4 байта.
Вы не сможете записывать менее 1 байт за раз.
Ответ 3
Что вы можете сделать, это записать его как биты (3) и заполнить его байтом с помощью 0.
Однако вам также необходимо запустить (или завершить) число бит (или бит из последнего байта), которые действительно используются.
например. (с использованием первого байта как длины):
00000011 -> 3, meaning from the last (and only byte in this case,
only the first 3 bits are used)
10100000 -> 101 is the string, other 5 bits are 0, just use for padding
В этом случае служебные данные первого (длинного) байта составляют 50%, чем длиннее строка, тем меньше процентная ставка.
Ответ 4
2 примечания по вашему подходу:
-
[Современные] Компьютеры не могут обрабатывать менее 1 байта в памяти, поэтому вы не сможете записывать отдельные биты на диск.
Кроме того, файловые системы обычно выделяют пространство в кусках (512 байт, 1Kb,...), где подходит файл. Итак, если у вас есть файл с 500 байтами, вы фактически теряете 512 байт дискового пространства.
-
atoi()
не преобразует из строки в двоичные числа, а в целое. Вы на самом деле пишете 0b1100101
, который 0d101
. Сначала вы должны выполнить преобразование. Что-то вроде:
char b = 0;
for (int i=0; c[i]!=NULL; i++)
{
b = ((b<<1) | atoi(c[i]));
}
Ответ 5
Вы не записываете биты 101
, а двоичное значение десятичного числа 101
, т.е. 1100101
. Поскольку вы fread
размером sizeof(x)
байтов, ваш файл будет sizeof(x)
байтов длиной.