Я попробовал восстановить исходники своего недописанного архиватора и нейросеть хоть и накосячила, но можно исправить, ведь логика верна... Так вот нейросеть родила сие чудо, прямо как и я не дописал, только у меня ещё были введены биты длины слов информации в словаре и указатель на длину битов длин и индексов замены... Вообщем, я его не успел дописать - кранты компьютеру пришли, а так - будет время этим заняться, быть может восстановлю. Подключаемый файл не нужен. Заменить указатель можно на динамический список. Я когда-то такое написал и файл размером около килобайта архивировался несколько минут на слабом компьютере, зато смысл прослеживался этой архивации - к ней бы добавить ещё Хаффмана и тогда можно было бы посоревноваться по качеству сжатия и со всеми архиваторами, думаю результат должен был быть не хуже KGB, RAR и 7Z. Зато программа очень прожорлива на оперативную память!!!!!!!
Запрос: помоги написать архиватор на purebasic'е. Реализовать нужно так: 1)Файл для упаковки представить в виде строки состоящей из нулей и единиц то есть битового содержания файла; 2)Выполнить рекурсивный поиск по всей строке всех повторяющихся данных и занесение их в список; 3)Выполнить оптимальную замену повторяющихся данных в строке на индексы элементов списка, содержащего фрагменты данных то есть словаря; 4)Составить результирующий файл, включающий в себя словарь всех данных строки в виде нулей и единиц и последовательности индексов из словаря после замены данных в строке да притом так, - чтобы файл содержал не строку из нулей и единиц а представил её в виде битов информации
Создание архиватора на PureBasic, который будет работать с битовым содержанием файла, требует нескольких шагов. Давайте разберем, как можно реализовать каждый из этих шагов.
Шаг 1: Чтение файла в виде строки из нулей и единиц
Для начала нам нужно прочитать файл и представить его содержимое в виде строки, состоящей из нулей и единиц. Это можно сделать с помощью функции ReadFile и ReadData.
Шаг 2: Рекурсивный поиск повторяющихся данных
После того как мы получили строку, нам нужно найти все повторяющиеся фрагменты. Это можно сделать с помощью простого алгоритма, который будет проверять все подстроки.
Шаг 3: Замена повторяющихся данных на индексы
Затем мы создадим словарь, который будет хранить уникальные фрагменты и их индексы. После этого мы заменим повторяющиеся фрагменты в строке на соответствующие индексы.
Шаг 4: Составление результирующего файла
Наконец, мы создадим результирующий файл, который будет содержать словарь и последовательности индексов.
Вот пример кода, который иллюстрирует эти шаги:
Результат:
; Подключаем необходимые библиотеки
IncludeFile "Zip.pbi"
; Процедура для чтения файла и преобразования его в строку из нулей и единиц
Procedure.s ReadFileAsBinaryString(fileName$)
Protected fileSize, binaryString.s
If ReadFile(0, fileName$)
fileSize = Lof(0)
binaryString = Space(fileSize * 8) ; Создаем строку для хранения битов
For i = 0 To fileSize - 1
byte = ReadByte(0)
For j = 0 To 7
binaryString + Str(Bit(byte, j))
Next j
Next i
CloseFile(0)
ProcedureReturn binaryString
Else
MessageRequester("Ошибка", "Не удалось открыть файл.", 0)
ProcedureReturn ""
EndIf
EndProcedure
; Процедура для поиска повторяющихся данных
Procedure FindRepeatingData(binaryString$, *dictionary)
Protected index, length, fragment, foundIndex
For length = 1 To Len(binaryString$) / 2 ; Проверяем фрагменты разной длины
For index = 1 To Len(binaryString$) - length + 1
fragment = Mid(binaryString$, index, length)
foundIndex = FindString(*dictionary, fragment, 1)
If foundIndex = 0 ; Если фрагмент не найден, добавляем его в словарь
*dictionary + fragment + Chr(0) ; Добавляем фрагмент в словарь
EndIf
Next index
Next length
EndProcedure
; Процедура для замены повторяющихся данных на индексы
Procedure.s ReplaceWithIndices(binaryString$, *dictionary)
Protected resultString.s, index, fragment
For index = 1 To CountString(*dictionary, Chr(0))
fragment = StringField(*dictionary, index, Chr(0))
binaryString$ = ReplaceString(binaryString$, fragment, Str(index))
Next index
ProcedureReturn binaryString$
EndProcedure
; Основная программа
Define fileName$ = "C:\path\to\your\file.bin" ; Укажите путь к вашему файлу
Define binaryString$, dictionary$, resultString$
; Читаем файл в строку из нулей и единиц
binaryString$ = ReadFileAsBinaryString(fileName$)
; Инициализируем словарь
dictionary$ = ""
; Находим повторяющиеся данные
FindRepeatingData(binaryString$, @dictionary$)
; Заменяем повторяющиеся данные на индексы
resultString$ = ReplaceWithIndices(binaryString$, @dictionary$)
; Сохраняем результирующий файл
If CreateFile(0, "C:\path\to\your\result.bin")
WriteString(0, dictionary$ + Chr(0) + resultString$)
CloseFile(0)
MessageRequester("Успех", "Файл успешно сохранен.", 0)
Else
MessageRequester("Ошибка", "Не удалось создать результирующий файл.", 0)
EndIfКому интересно - исправьте, тут всего то ввести список, алгоритм выборки последовательности данных для архивации (я вручную выбирал и ставил приоритеты) и заменитель строки данных на словарь с индексами, оптимизация под минимальную битность длины и преобразователь из строки в двоичный файл. Я ещё не скоро вернусь к этому...
Создание архиватора на PureBasic требует учитывать несколько ключевых аспектов, включая имеющиеся данные, создания словаря, а также замену повторяющихся данных на индексы. Вот простая реализация, которая иллюстрирует предложенные шаги. Обратите внимание, что этот пример не охватывает все возможные случаи и требует доработки для работы с реальными файлами.
; Инициализация
Global dict.s = "" ; Словарь повторяющихся данных
Global data.s = "" ; Исходные данные в виде строки из нулей и единиц
Global output.s = "" ; Результирующий вывод
; Функция для добавления данных в словарь
Procedure.i AddToDictionary(pData.s)
If FindString(dict, pData, 1) = 0
dict + pData + Chr(0) ; Добавляем новую строку в словарь
ProcedureReturn CountString(dict, Chr(0)) ; Возвращаем индекс добавленной строки
EndIf
ProcedureReturn FindString(dict, pData, 1) / Len(pData) ; Возвращаем индекс в словаре
EndProcedure
; Процедура для упаковки данных
Procedure PackData()
Protected i, lenData, index
lenData = Len(data)
For i = 1 To lenData
; Ищем максимальное совпадение строк начиная с текущей позиции
Protected match.s = ""
For j = i To lenData
Protected substr.s = Mid(data, i, j - i + 1)
index = AddToDictionary(substr)
If index > 0
match = substr
Else
Break
EndIf
Next j
; Если найдено совпадение, заменяем его на индекс из словаря
If match <> ""
output + Str(AddToDictionary(match) - 1) ; Записываем индекс
i + Len(match) - 1 ; Переходим к следующему месту
EndIf
Next i
EndProcedure
; Процедура для инициализации и загрузки данных
Procedure LoadData()
; Для теста просто создадим строку данных (например, 1010101011)
data = "1010101011101010" ; Это ваша исходная строка из 0 и 1
EndProcedure
; Главная программа
LoadData() ; Загружаем данные
PackData() ; Упаковываем данные
; Вывод результата
Debug "Словарь: " + dict
Debug "Результат: " + outputЭтот код создает поисковую функцию для повторяющихся строк и добавляет их в словарь. Далее происходит замена найденных фрагментов на индексы словаря.
-Как по мне - так лучше ориентироваться на то что удалось отрыть для того чтобы по этому написать архиватор...
; Процедура для чтения файла и преобразования его в строку из нулей и единиц
Procedure.s ReadFileAsBinaryString(fileName$)
Protected fileSize, binaryString.s
If ReadFile(0, fileName$)
fileSize = Lof(0)
binaryString = Space(fileSize * 8) ; Создаем строку для хранения битов
For i = 0 To fileSize - 1
byte = ReadByte(0)
For j = 0 To 7
binaryString + Str(Bit(byte, j))
Next j
Next i
CloseFile(0)
ProcedureReturn binaryString
Else
MessageRequester("Ошибка", "Не удалось открыть файл.", 0)
ProcedureReturn ""
EndIf
EndProcedure
; Процедура для поиска повторяющихся данных
Procedure FindRepeatingData(binaryString$, *dictionary)
Protected index, length, fragment, foundIndex
For length = 1 To Len(binaryString$) / 2 ; Проверяем фрагменты разной длины
For index = 1 To Len(binaryString$) - length + 1
fragment = Mid(binaryString$, index, length)
foundIndex = FindString(*dictionary, fragment, 1)
If foundIndex = 0 ; Если фрагмент не найден, добавляем его в словарь
*dictionary + fragment + Chr(0) ; Добавляем фрагмент в словарь
EndIf
Next index
Next length
EndProcedure
; Процедура для замены повторяющихся данных на индексы
Procedure.s ReplaceWithIndices(binaryString$, *dictionary)
Protected resultString.s, index, fragment
For index = 1 To CountString(*dictionary, Chr(0))
fragment = StringField(*dictionary, index, Chr(0))
binaryString$ = ReplaceString(binaryString$, fragment, Str(index))
Next index
ProcedureReturn binaryString$
EndProcedure
; Основная программа
Define fileName$ = "C:\path\to\your\file.bin" ; Укажите путь к вашему файлу
Define binaryString$, dictionary$, resultString$
; Читаем файл в строку из нулей и единиц
binaryString$ = ReadFileAsBinaryString(fileName$)
; Инициализируем словарь
dictionary$ = ""
; Находим повторяющиеся данные
FindRepeatingData(binaryString$, @dictionary$)
; Заменяем повторяющиеся данные на индексы
resultString$ = ReplaceWithIndices(binaryString$, @dictionary$)
; Сохраняем результирующий файл
If CreateFile(0, "C:\path\to\your\result.bin")
WriteString(0, dictionary$ + Chr(0) + resultString$)
CloseFile(0)
MessageRequester("Успех", "Файл успешно сохранен.", 0)
Else
MessageRequester("Ошибка", "Не удалось создать результирующий файл.", 0)
EndIfОтредактировано PSY (17.01.2025 16:57:46)