Я попробовал восстановить исходники своего недописанного архиватора и нейросеть хоть и накосячила, но можно исправить, ведь логика верна... Так вот нейросеть родила сие чудо, прямо как и я не дописал, только у меня ещё были введены биты длины слов информации в словаре и указатель на длину битов длин и индексов замены... Вообщем, я его не успел дописать - кранты компьютеру пришли, а так - будет время этим заняться, быть может восстановлю. Подключаемый файл не нужен. Заменить указатель можно на динамический список. Я когда-то такое написал и файл размером около килобайта архивировался несколько минут на слабом компьютере, зато смысл прослеживался этой архивации - к ней бы добавить ещё Хаффмана и тогда можно было бы посоревноваться по качеству сжатия и со всеми архиваторами, думаю результат должен был быть не хуже 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 (Вчера 16:57:46)