Страница: 1 | 2 |
Вопрос: ПоБИТовая работа с файлами
Добавлено: 11.06.06 08:53
Автор вопроса: ZagZag | ICQ: 295002202
Надо записать в файл определенное кол-во бит указанного значения (от 1 до
255). Причем записывать надо не одну последовательность, а несколько.
Будет здорово если у кого-нибудь найдется процедура с параметрами типа:
позиция в файле (в битах), длина записи (в битах), значение бита
Уже всю голову изломал над проблемой
Для упрощения задачи уточню что именно я делаю:
Есть массив со значениями длин битовых цепочек (а как их еще назвать)
Этот массив нужно записать в файл и в дальнейшем его оттуда считать
Для этого потребуется чередовать значения битов (010101...) чтобы в
дальнейшем можно было получить значения обратно в массив
Пример:
Массив (тип Byte): {4,1,3,2,1}
В файле должно быть записано:
&b11110111.00100000
&hF7.20
Думаю если найдется процедура записи, то процедуру чтения я напишу сам, но
если и такая есть то буду вдвойне благодарен
PS
В сети не буду дня 3. Буду рад любым информативным ответам.
Ответы
Всего ответов: 18
Номер ответа: 1
Автор ответа:
Sharp
Лидер форума
ICQ: 216865379
Вопросов: 106
Ответов: 9979
Web-сайт:
Профиль | | #1
Добавлено: 11.06.06 15:34
Для чтения-записи используй CreateFile, SetFilePosition, WriteFile, ReadFile. По байтам они пишут именно так. Если нужно по битам (которые от 0 до 1), то сперва придется байты сформировать.
Номер ответа: 2
Автор ответа:
HACKER
Разработчик Offline Client
Вопросов: 236
Ответов: 8362
Профиль | | #2
Добавлено: 11.06.06 23:28
да судя с примера
Массив (тип Byte): {4,1,3,2,1}
В файле должно быть записано:
&b11110111.00100000
&hF7.20
всё гораздо проще...
ему просто надо данные в бинарные данные перевести и записать в файл...
2 ZagZag
Алгоритмов полно, даже тут на форуме берёшь код символа, далее с ним вычисления которые записываются с права на лево... А вычисление все - всё делить не 2, и если есть остаток записывать 1, если нет 0...
6
6 / 2 = 3 (остатка нет) => 0
3 / 2 = 1,5 (остаток есть) => 1
1 / 2 = 0,5 (остаток есть) => 1
и того 6 в двоичном представлениии:
110
Осталось реализовать
Номер ответа: 3
Автор ответа:
ZagZag
ICQ: 295002202
Вопросов: 87
Ответов: 1684
Профиль | | #3
Добавлено: 12.06.06 02:28
2Sharp
1 до
255)
Я наверное не правильно выразился Мне нужно записать/считать указанное
количество бит определенного значения в бинарный файл.
Я правильно тему назвал. Я же не новичек уже. В данном случае нужна именно
поБИТовая работа с файлами. Как побайтно работать я знаю.
Пример:
'Массив из длин битовых цепочек: {4,1,3,2,1}
Dim arData(4) As Byte
arData(0) = 4: arData(1) = 1: arData(2) = 3: arData(3) = 2: arData(4) = 1
Open "C:\data.dat" For Binary Access Write As #1
For i = 0 To 4
'А вот тут надо в файл записать биты:
'Для четных элементов arData - нули, для нечетных - единички
'Количество записываемых бит - значение arData(i)
'Положение записи в файл - lngBitOffset
lngBitOffset = lngBitOffset + arData(i)
Next
Close #1
В результате в файле должно быть записано всего 2 байта(!):
0xF7 20
Чтобы было яснее в бинарном виде это будет:
11110111 - Элементы arData(0), arData(1), arData(2)
00100000 - Элементы arData(3), arData(4) и 5 пустых бит (ведь
полбайта не запишешь ), значение которых всегда должно быть неравным
последней битовой цепочке
Сам себя процитирую
Я это конечно же знаю, т.ч. предлагаю вычислять значение байта для записи
заранее, до того как он будет заполнен или пока не кончатся данные
Это реализовать нужно на PowerBasic. Я еще попытаюсь использовать его тип
BIT, но вроде он здесь не подойдет
PS
Я всетаки не удержался проверить почту... думаю проверю еще не раз
Спасибо за ответы
Попытаюсь использовать CreateFile, SetFilePosition, WriteFile, ReadFile
(хотя тестить я думаю лучше на Open, Seek, Put, Get) и бинарную математику
Номер ответа: 4
Автор ответа:
HACKER
Разработчик Offline Client
Вопросов: 236
Ответов: 8362
Профиль | | #4
Добавлено: 12.06.06 05:40
ну взять arData(0), посмотреть что в нём чётное значение, значит лепим единицы, затем посмотреть какое значение в arData(0) - знаем сколько единиц лепить... налепили последовательность, единиц/нулей, перевели её в десятичное представление, десятичное перевели в ascii и записали байт в файл. У тебя сам алгоритм неполучается, или что?
Номер ответа: 5
Автор ответа:
ZagZag
ICQ: 295002202
Вопросов: 87
Ответов: 1684
Профиль | | #5
Добавлено: 13.06.06 02:14
Нет-нет, если индекс массива четный - лепим единицы, а не значение его элемента.
Да, вобщем-то интересует алгоритм.
А точнее - как в файл записать не кратное 8 кол-во бит
Еще уточню что данные будут браться не из массива, а из файла... размер которого может быть большой, т.ч. его в память целиком не загрузишь и результат чисто в памяти сформировать не получится, т.к. результат тоже не мало места займет.
На самом деле задачка интересная. Увы сегодня я над ней не думал... спал.
Номер ответа: 6
Автор ответа:
Morpheus
Вопросов: 224
Ответов: 3777
Web-сайт:
Профиль | | #6
Добавлено: 13.06.06 03:07
А если первые несколько байт (ну, по традиции, четыре или можно пять так как биты) отдать под запись длины файла и указать сколько надо в файле считать бит, а потом такое количество бит и записать. конец последнего байта тупо заполнить нулями...
конечно на вопрос это не отвечает и вообще тривиальщина, но вдруг поможет
Номер ответа: 7
Автор ответа:
ZagZag
ICQ: 295002202
Вопросов: 87
Ответов: 1684
Профиль | | #7
Добавлено: 13.06.06 03:47
2Morpheus, ты предлагаешь записать количество всех значимых бит в файле?
Это моей задаче не поможет, т.к.:
1. Займет лишних 4-5 байта
2. Мне надо будет всеравно как-то различать при считывании границы начала-окончания каждой битовой цепочки (для вычисления ее длины), а. для этого их значения (0 и 1) должны чередоваться.
Записывать длины цепочек как байты, а не как битовые цепочки определенной длины мне тоже не подойдет, т.к. это сведет весь эффект сжатия на НЕТ (я пишу вещь на подобии архиватора)
Не хотел говорить, но в кратце опишу алгоритм сжатия (кста, может я велосипед изобретаю?)
1. Подсчитать в массив arChars() встречаемость каждого символа в исходном файле
 O UNTIL EOF(lngSrcFile)
GET #lngSrcFile,,bytSymbol
Symbols(bytSymbol) = Symbols(bytSymbol) + 1
Indexes(bytSymbol) = bytSymbol
LOOP
2. Сортировать полученные массивы по Indexes()
ARRAY SORT Symbols(), TAGARRAY Indexes(), DESCEND
3. Записать в файл Indexes()
4. Перебирать побайтно #lngSrcFile и в #lngDestFile записывать биты
! XOR eax, eax
! MOV lngCount, eax
 O UNTIL Indexes(lngCount) = bytSymbol
! ADD lngCount, 1
LOOP
! ADD lngCount, 1
bitData = NOT bitData
'Собственно запись бит
'...
'/Собственно запись бит
lngWritedBitsCount = lngWritedBitsCount + lngCount
Значение битовой цепочки = bitData
Длина битовой цепочки = lngCount
Смещение = lngWritedBitsCount
Вот вроде и весь процесс архиваци
PS
Алгоритм (c) Сехан Алексей Петрович
Это не я
Номер ответа: 8
Автор ответа:
HACKER
Разработчик Offline Client
Вопросов: 236
Ответов: 8362
Профиль | | #8
Добавлено: 13.06.06 05:12
ну это теоретически невозможно. Ну подумай...
1,5 (полтора) байт ?
выход, как уже сказили, сформировать из битов - байт. Но при этом всёравно как не крути 1 байт будет равен 8 битам. И никак и никогда нельзя записать на винт "пол байта"...
Даже если попробовать такое замутить на ассемблере, работая с винтом на самом низком уровне, и с процессором в самом нулевом кольце и вдруг получится записать "пол байта" и винт при это не подавится то всё это акруально будет до первого скандиска...
Алгоритмы архивации основаны совершенно на другом принципе, а именно на сдвиге битов... Но в файл пишутся всё те же байты, только на выходе их уже поменше
Номер ответа: 9
Автор ответа:
ZagZag
ICQ: 295002202
Вопросов: 87
Ответов: 1684
Профиль | | #9
Добавлено: 13.06.06 05:40
Понимаю что ПОЛБАЙТА звучит дико
В файл конечно должны писаться байты (и ничего меньше)
Но как эти байты динамически формировать из поставленной задачи?
В принципе можно сделать некий буффер (наверное так лучше назвать) в котором из данных бит будут формироваться байты. Байты должны формироваться до тех пор, пока количество составляющих их ЗНАЧАЩИХ (те которые собственно являются данными из битовых цепочек) бит станет кратным 8. в итоге и получится строка или массив, который и запишется на диск. После чего буффер обнулится и продолжится его заполнение новыми данными.
Внимание вопрос: Как сформировать этот буффер?
Прийдется делать что-то вроде двойного цикла?
'lngCount - Количество записываемых бит
'bitData - Значение записываемых бит
For lngIndex = 0 To lngCount
For lngIndexByBits = 1 To 8
'Последний_эл-т_буффера or IIF(bitData,1,0) * lngIndexByBits
'Длина_бит = Длина_бит + 1
'(Длина_бит mod 8) = 0 then
' Записать и обнулить буффер
Next
Next
Что-то вроде того должно получиться Надо будет попробовать... А чем лучше буффер реализовать?
PS
Я как понял... ни кто этим не занимался? Или жадные все... Чтож буду первоПРОХОДИМЦЕМ
Номер ответа: 10
Автор ответа:
ZagZag
ICQ: 295002202
Вопросов: 87
Ответов: 1684
Профиль | | #10
Добавлено: 13.06.06 05:49
Не учел того что начинать запись прийдется с позиции бит, кратной 8. Можно конечно это доработать, но для моей задачи это не нужно
Еще забыл указать что после обнуления буффера, надо обнулять и переменную Длина_бит чтобы не было переполнения
И вообще мне этод метод с буффером неопределенной длинны не нравится - фиг знает сколько прийдется записывать цепочек со значением 254... Вроде 4 штуки, т.к. 254*4=1016 1016 mod 8 = 0 Итого, длина буффера 127 байт
Номер ответа: 11
Автор ответа:
HACKER
Разработчик Offline Client
Вопросов: 236
Ответов: 8362
Профиль | | #11
Добавлено: 13.06.06 21:01
да лучше в виде функции которая возвращает байт, а принимает массив arData. А внутри неё считается биты и собственно формируется байт...
Биты собирай хоть в строку...
строку из битов преобразовуй в десятичное чисто, это число Chr в байт и его возвращай...
Номер ответа: 12
Автор ответа:
Sharp
Лидер форума
ICQ: 216865379
Вопросов: 106
Ответов: 9979
Web-сайт:
Профиль | | #12
Добавлено: 13.06.06 22:27
Где ты такую забористую траву берешь?
Номер ответа: 13
Автор ответа:
HACKER
Разработчик Offline Client
Вопросов: 236
Ответов: 8362
Профиль | | #13
Добавлено: 14.06.06 04:13
иш какой, тебе скажи Та лана, чё для своих выпаду думаешь, вали в Харьков, я покажу... где и какую и у кого
Номер ответа: 14
Автор ответа:
HOOLIGAN
Вопросов: 0
Ответов: 1066
Профиль | | #14
Добавлено: 14.06.06 12:07
Долго читал, несколько раз перечитывал, ничего не понял
У тебя одна из проблем в том, что не хочешь терять пространство на запись последних незначащих нулей? Если так, откажись от байта как единицы готовой (сформированой) информации и перейди к дворду или qword'у. Количество нерационально используемых бит уменьшится соответственно в 4 или 8 раз.
Номер ответа: 15
Автор ответа:
Victor
ICQ: 345743490
Вопросов: 42
Ответов: 385
Web-сайт:
Профиль | | #15
Добавлено: 14.06.06 13:35
Пусть записываем набор из n битов, начиная с бита № StartBitPos в файл. Для этого:
1. Читаем байты файла, покрываемые этим набором бит. От есть байты от StartBitPos\8 до (StartBitPos + n + 7)\8
2.конвертируем полыченнйе байты в биты Делаем массив битов. Его начало будет соответствовать биту № (StartBitPos\8)*8 файла.
3. Пишем в прочитанную последовательность битов наши n штук
4. Конвертируем биты обратно в байты и пишем байты в файл.
Вот код для конвертирования битов в байты и обратно:
Dim i As Long, j As Long, h As Long
Dim bUB As Long, cUB As Long
Dim tB As Byte
bUB = UBound(Arr)
cUB = bUB \ 8
ReDim Preserve Arr(0 To (cUB + 1) * 8 - 1)
For i = 0 To cUB
tB = 0
h = i * 8
For j = 0 To 7
tB = tB + Arr(h + j) * Stepen2(j)
Next j
Arr(i) = tB
Next i
ReDim Preserve Arr(0 To cUB)
End Sub
Public Sub BytesToBits(ByRef Arr() As Byte)
Dim i As Long, j As Long, h As Long
Dim UB As Long, NUB As Long
UB = UBound(Arr)
NUB = (UB + 1) * 8 - 1
ReDim Preserve Arr(0 To NUB)
For i = NUB To 0 Step -1
j = i \ 8
h = i Mod 8
Arr(i) = (Arr(j) Mod Stepen2(h + 1)) \ Stepen2(h)
Next i
End Sub
Я не уверен, что все это работает, так как писал примерно год назад и не помню даже, тестировал или нет.
Stepen2 - массив, в котором записаны степени двойки (от нуля до ??? наверно 9-ти)
Алгоритм наверняка не отличается производительностью, но все-таки..