Введение.
|
В этой статье я рассмотрю способ
побитной работы с файлами. Чащё всего при работе с файлами для
записи данных можно обойтись процедурами
BlockRead
/
BlockWrite
, но иногда этого бывает
битов недостаточно. Например, когда нужно в первые 3 бита
файла записать число 5, в следующие 7 - другое число и тд. У
тех, кто никогда не сталкивался, эта задача может вызвать
сильное затруднение. Для того чтобы его не возникло, как раз и
написана эта статья.
|
Приведу два конкретных примера, когда с
файлами необходимо работать побитно:
-
При
сжатии и архивировании файлов.
-
При
чтении графических файлов(BMP, GIF и др.).
|
Операции с битами.
|
Перед тем как начать описание скажу
пару слов про операции с битами, которые дальше буду
использовать.
|
[число] shl [на сколько сдвинуть]
-
Сдвиг битов влево.
I := 1
shl
2;
// I = 4
(4 = 100
2
)
[число] shr [на сколько сдвинуть]
- Сдвиг битов вправо.
I := 3
shr
2;
// I = 0
(3 = 11
2
)
[число] or [число]
- побитное
"или".
I
:= 3
or
2;
// I = 3 (2 =
10
2
)
[число] and [число]
- побитное
"и".
I :=
5
and
2;
// I =
0 (5 = 101
2
)
|
Если вы незнакомы с ними и моё краткое
пояснение нечего не дало, думаю, вы без труда сможете найти
инфу о них в сети. Если же нет, пишите мне ваши вопросы на
мыло
, или оставляйте их
на
форуме
.
|
|
Запись.
|
Итак, нам нужно последовательно
записывать в файл группы битов разной длины. А Делфи позволяет
минимально записать только 1 байт, то есть если нам нужно
записать только 3 бита мы этого сделать не сможем. Но почему
бы не сохранить эти 3 бита в буфере (в качестве него,
например, можно использовать переменную типа word), и так же
поступить и с другими записываемыми битами. А когда кол-во бит
в буфере превысит (или станет равно) 8, можно будет произвести
запись в файл. Как видите всё довольно просто! Вот процедура
производящая побитную запись в файл:
|
{ Процедура записи в
файл }
Procedure
BitWrite( Num : LongWord;
{ Записываемые биты }
NumBit :
Integer);
{ Их количество }
var
B : Byte;
{ Промежуточная переменная нужная для записи
}
begin
Bits := Bits
or
( Num
shl
CounterBit );
{
Добавляем в буфер новые биты }
inc(
CounterBit, NumBit );
{ Увеличиваем
значение счётчика }
{ Пока значение счётчика позволяет - записываем
в файл }
While
( CounterBit >= 8 )
do
begin
B := Bits
and
;
{ Получаем первый байт из буфера }
BlockWrite( BitFile, B, 1
);
{ Записываем его }
Bits
:= Bits
shr
8;
{ Отчищам буфер от
записанных бит }
Dec(
CounterBit, 8 );
{ понижаем значание
счётчика }
end;
end;
|
Думаю почти всё здесь должно быть
понятно, но всё равно поясню некоторые моменты.
|
Bits := Bits
or
( Num
shl
CounterBit );
{ Добавляем в буфер новые
биты }
Чтобы добавить в буфер
новые биты, и не стереть уже добавленные, мы просто сдвигаем
новые влево на столько, чтобы они не они находились как раз за
добавленными. А потом совмещаем оператором
or
.
|
B := Bits
and
;
{ Получаем первый байт из буфера }
Число
= 11111111
2
. В результате операции
and
над
ним и буфером, мы получим первый байт буфера.
|
Теперь с помощью процедуры BitWrite
можно осуществлять побитную запись в файл, но при таком
алгоритме записи остаётся одна проблема: когда запись
заканчивается в буфере может остаться несколько незаписанных
бит. Её можно решить с помощью процедуры
EndBitWrite
,
которую нужно вызвать при завершении записи.
|
Procedure
EndBitWrite;
var
B : Byte;
begin
{ Если буфер не пустой,
записываем данные из буфера в файл }
if
( CounterBit > 0 )
then
begin
B := Bits;
BlockWrite( BitFile, B, 1 );
CounterBit := 0;
{ Обнулим счётчик битов }
end;
end;
|
Так как в буфере не может остаться
больше 7 байт, нам нужно просто проверить, не пустой ли буфер,
и если нет, дописать его в файл.
|
Чтение.
|
При чтении нам необходимо совершить
почти такие же действия как и при записи, с небольшими
изменениями:
|
{ Процедура чтения из файла }
Procedure
BitRead(
out
Num : LongWord;
{ Куда читать }
NumBit : Integer);
{ Сколько читать }
var
B : Byte;
begin
{ Пока в буфере не хватает бит - читаем их из файла }
While
CounterBit < NumBit
do
begin
BlockRead( BitFile, B, 1 );
{ Читаем ещё один байт }
Bits := Bits
or
( B
shl
CounterBit );
{ Добавляем его в буфер }
inc( CounterBit, 8 );
end;
Num := Bits
and
((1
shl
NumBit) - 1);
{ Получаем из буфера нужное кол-во бит }
Bits := Bits
shr
NumBit;
{ Отчищаем буфер от выданных бит }
dec(CounterBit, NumBit);
end;
|
Тут тоже немного поясню.
|
While
CounterBit <
NumBit
do
{ Пока в буфере не
хватает бит - читаем их из файла }
Сначала наполняем буфер
пока в нём не будет нужное (или большее) кол-во бит, а потом
из него записываем в переменную вывода.
Num := Bits
and
((1
shl
NumBit) - 1);
{ Получаем из буфера нужное кол-во бит }
Чтобы
взять из буфера нужное число бит мы устанавливаем столько же
бит в единицу и сравниваем с буфером.
|
Заключение.
|
Данные процедуры очень простые и
возможно не подойдут для решения некоторых задач. Но их можно
легко изменить, так как вам будет нужно. Я только показал
общий пример. Если у вас возникли вопросы, вы заметили ошибку
в статье - заходите на
форум
или пишите на
мыло
.
|
Также можете скачать
пример
- простое консольное приложение, в которых демонстрируется
работа данных процедур.
|
|
|
Хакер подходит к телефону:
Звонящий: Алло!
Хакер: Проверка пользователя и пароля.
Звонящий: Алло! Что такое?! Что случилось?
Хакер: Для
справки нажмите F1.
Звонящий: Какое F1!!! У меня дисковый
телефон!
Хакер: Тогда вставьте Диск N2 и нажмите Enter.
Звонящий: Какой диск! Какое F1! Васю можно?!
Хакер: Указаный
Вами пользователь не найден, повторите попытку позже.
****
Системные и прикладные
программисты едут на конференцию.
Встречаются у касс вокзала, где
и те и другие берут билеты. Прикладники покупают по билету на нос,
системщики берут один билет. Удивленные прикладники спрашивают:
-
У вас че только один человек едет?
- Да нет. Все.
- А как же
вы?
- А это наши трудности.
В поезде прикладники занимают
места согласно купленных билетов за полчаса до отправления. За 45
сек. До отхода появляется стая системщиков. С криками "Мы товарища
провожаем" вся толпа врывается в вагон закрывается в
туалете.
Поезд трогается. Контроллер подходит к туалету и стучит.
Высовывается рука, протягивает билет. Через некоторое время
системщики, как тараканы, расползаются по поезду.
Едут обратно.
Опять встречаются на вокзале. Прикладники, укравшие копирайт берут
один билет. Системщики билета не берут.
За 45 сек до отхода
врывается толпа прикладников и запирается в туалете.
Поезд
трогается. Стук в дверь туалета. Выосвывается рука, протягивает
билет. Системщик хватает билет и бежит в другой туалет.
***
В одном из ВУЗов
выпускникам - пpогpаммистам задали вопpос: "Вы сели в самолет, и вам
сообщили, что пpогpамму для боpтовых компьютеpов писали вы сами. Что
вы будете делать?" Все студенты дpужно ответили "Постаpаюсь
выбpаться из этого самолета и полететь следующим pейсом", а один
ответил "Hичего не буду делать.". И пояснил: "С моей пpогpаммой этот
самолет даже на взлетку не выpулит..."
***
Лежит програмист
в постели с девушкой, водит по ней пальцем и приговаривает:
-
Что-то я не пойму, где здесь вход на сайт, а где просто
баннеры?
***
Поломка бортового
компьютера на станции МИР. Центр Управления Полетов (ЦУП).
Пресс-конференция:
"... нет особых причин для волнения. На
станции компьютер в рабочем состоянии. Отказали только две
программы... пасьянс и сапер..."
***
Попал программист на
необитаемый остров. Ничего вокруг. Только несколько банановых и
кокосовых деревьев. Четыре месяца он питался фруктами и все смотрел
в океанскую даль в надежде на корабль. Весь зарос. И вот в один
прекрасный день из-за угла острова показалась лодка, которой правила
прекрасная женщина.
Программист:
- Откуда ты взялась?
Женщина:
- Я с другой стороны острова. Я тоже потерпела
кораблекрушение.
Программист:
- А где ты раздобыла лодку?
Женщина:
- Я сделала ее собственными руками. Дно из пальмы,
весла из резинового дерева и корма из эвкалипта. Из разных камней я
изготовила необходимые инструменты. Но хватит об этом. Где ты
живешь? Программист со стыдом признался, что вот уже четвертый месяц
как ночует на песке.
Женщина:
- Ну, так поехали ко мне.
Когда они приплыли к ее месту, программист, не веря своим глазам,
увидел двухэтажный бамбуковый дом, выкрашенный в белый и синий
цвета. Вокруг росли деревья. Они вошли в дом. Там было полно разных
хитроумных приспособлений, сделанных из природных материалов.
Женщина предложила выпить. Программист естественно согласился. И вот
они уже на диване из пальмовых листьев.
Женщина:
- А ты
всегда носил бороду?
Программист:
- Нет, я обычно брился.
- Ну... если ты хочешь побриться, то там наверху есть бритвенный
прибор из ракушек. Программист побрился, сошел вниз, снова уселся на
диван из листьев. Тут появилась и женщина в одном только фиговом
листе и пахнущая фиалкой и сказала:
- Скажи мне, ты вот был
один-одинешенек на протяжении долгого времени. Ты, наверно,
соскучился по компании... ты понимаешь, что я имею ввиду?.. В чем
все женщины и мужчины нуждаются?... Что-то такое, что было бы
приятным прямо вот здесь, прямо сейчас...
Программист:
-
Да... есть такое желание... скажи-ка мне... а... у тебя есть доступ
к... Интернету...
(Я долго сидел
и читал этот анекдот. А он тупой. Зря читал. Ну чтобы я не был один
такой пострадавший - теперь вы знаете что я
чувствовал...)
***
Встречаются два
программиста:
- Говорят, ты женился!
- Да, есть такое дело.
- А как зовут?
- (в задумчивости) Окс... нет, Тат..., КОРОЧЕ
ICQ#9876543210!
***
Идет квакер из клуба
после 15 часов упорной работы...
Идет, а вокруг - облака, птицы,
трава и т.д.... Думает:
- Вот ведь какая красотища! И без
всякого OpenGL!
***
Один компьютерщик
рассказывает другому:
- Представляешь, вчера возвращаюсь с
работы чуть раньше обычного, а у жены в постели - незнакомый мужик.
И глаза у обоих хитрые-хитрые... Я сразу неладное заподозрил,
кинулся к компьютеру, пытаюсь выйти в Интернет - а они,
с
#
ки, пароль
сменили...
***
Гарри Каспаров наконец-то
выиграл у компьютера и с двумя очками и тремя жизнями перешел на
следующий уровень
!
***
Институт. Большая
аудитория. Идет лекция. Вдруг открывается дверь, и заваливается
пьяный студент-фидошник.
- Здравствуйте! Это тест! Меня
видно?
***
- Что для геймера Жизнь?
- Два компакта с "Half-Life"!
***
Встречаются два квакера:
- Ты знаешь, по-моему Квейк сильно на психику влияет. Вот
сегодня ночью кошмарный сон снился: будто я в аду, а вокруг монстры,
лава, кровь...
- Ну и как?
- Как, как?! До пятого уровня
дошел!
***
Под утро она тихонько
выскользнула из-под одеяла, на цыпочках подошла к столу, включила ПК
и несколька раз преподняв уронила системный блок, порезала на
кусочки шнур от клавиатуры и мыши, собрала все CD в старую простыню,
вынесла их на помойку и тщательно побила молотком. После чего
вернулась в постель и уснула со счастливой улыбкой на губах,
прижавшись к широкой спине мужа. Жить ей оставалось не больше
часа...
***
Ты уверен, что хочешь
выключить компьютер?" - спросил компьютер.
Со словами "не хочу,
но надо!" Штирлиц в пятидесятый раз за последние двадцать минут
нажимал на кнопку "Нет".
***
- Плодитесь и pазмножайтесь... -
сказал Бог.
- А я вас буду отстpеливать... - добавил
КоМодератор.
***
Попал фидошник в ад. Ему черт
говорит:
- Тебе определено 1000 лет наказания, но т.к. я люблю
анекдоты, то разрешаю их тебе рассказывать. Пока ты их
рассказываешь, этот срок будет вычтен из твоего наказания.
Ну,
фидошник начинает травить анекдоты. Год... два... 100 лет... 900 лет
прошло, он все рассказывает. Наконец, на 999 году замолкает.
-
Все, анекдоты закончились? Ну, давай хоть год тебя помучаю.
- Да
погоди ты, сейчас вторую часть оффтопик-листа
достану!
|