Nano Hash - криптовалюты, майнинг, программирование

Декодирование/кодирование текстового файла с использованием библиотеки стека - невозможно кодировать большие файлы С++

Я работаю над программой, которая может кодировать, а затем декодировать текст на С++. Я использую библиотеку стека. Принцип работы программы заключается в том, что сначала она запрашивает у вас ключ шифрования, который вы вводите вручную. Затем он запрашивает имя файла, который является текстовым файлом. Если это обычный текстовый файл, сообщение кодируется в новый файл и добавляется расширение .iia. Если текстовый файл уже имеет расширение .iia, то он декодирует сообщение, если ключ шифрования совпадает с тем, который использовался для его кодирования.

Моя программа кодирует и декодирует, но количество символов, которые она декодирует, определяется temp.size() % cypher.length(), который находится в цикле while в функции readFileEncode(). Я думаю, это то, что мешает кодированию всего файла, а затем правильно декодировать. Другими словами, в конечном файле после декодирования, скажем, из «example.txt.iia» обратно в «example.txt» отсутствует большая часть текста из исходного файла «example.txt». Я пробовал только cypher.length(), но, конечно, это ничего не кодирует и не декодирует. Весь процесс определяется этим аргументом для декодирования и кодирования.

Кажется, я не могу найти точную логику для кодирования и декодирования всех символов в файле любого размера. Вот следующий код для функции, которая выполняет декодирование и кодирование:

РЕДАКТИРОВАТЬ: Используя код WhozCraig, который он отредактировал для меня:

void readFileEncode(string fileName, stack<char> &text, string cypher)
{
    std::ifstream file(fileName, std::ios::in|std::ios::binary);
    stack<char> temp;
    char ch;

    while (file.get(ch))
        temp.push(ch ^ cypher[temp.size() % cypher.length()]);

    while (!temp.empty())
    {
        text.push(temp.top());
        temp.pop();
    }
}

РЕДАКТИРОВАТЬ: требуется стек. Я собираюсь реализовать свой собственный класс стека, но сначала я пытаюсь заставить его работать с библиотекой стека. Кроме того, если есть лучший способ реализовать это, пожалуйста, дайте мне знать. В противном случае, я считаю, что в этом нет ничего плохого, кроме как заставить его пройти цикл для кодирования и декодирования всего файла. Я просто не уверен, почему он останавливается, скажем, на 20 символах иногда или на десяти символах. Я знаю, что это также связано с длиной шифра, поэтому я считаю, что это связано с% (мод). Только не знаю как переписать.

РЕДАКТИРОВАТЬ: Хорошо, попробовал решение WhozCraig, и я не получаю желаемого результата, поэтому теперь ошибка должна быть в моем файле main. Вот мой код для основного:

#include <iostream> 
#include <iomanip> 
#include <fstream>
#include <string> 
#include <cstdlib>
#include <cctype>
#include <stack>


using namespace std;

void readFileEncode(string fileName, stack<char> &text, string cypher);

int main()
{
    stack<char> text;   // allows me to use stack from standard library
    string cypher;
    string inputFileName;
    string outputFileName;
    int position;

    cout << "Enter a cypher code" << endl;
    cin >> cypher;
    cout << "Enter the name of the input file" << endl;
    cin >> inputFileName;

    position = inputFileName.find(".iia");//checks to see if the input file has the iia extension

    if (position > 1){
        outputFileName = inputFileName;
        outputFileName.erase(position, position + 3);// if input file has the .iia extension it is erased 
    }
    else
        //outputFileName.erase(position, position + 3);// remove the .txt extension and
        outputFileName = inputFileName + ".iia";// add the .iia extension to file if it does not have it

    cout << "Here is the new name of the inputfile " << outputFileName << endl; // shows you that it did actually put the .iia on or erase it depending on the situation

    system("pause");

    readFileEncode(inputFileName, text, cypher); //calls function            

    std::ofstream file(outputFileName); // calling function

    while (text.size()){// goes through text file
        file << text.top();
        text.pop(); //clears pop
    }

    system("pause");
}

По сути, я читаю файл .txt для шифрования, а затем помещаю расширение файла .iia в имя файла. Потом прохожу обратно, ввожу файл обратно с расширением .iia, чтобы раскодировать его обратно. Когда я расшифровываю это обратно, это тарабарщина примерно после первых десяти слов.

@WhozCraig Имеет ли значение, какие пробелы, новые строки или знаки препинания есть в файле? Может быть, с полным решением здесь вы можете указать мне, что не так.


  • Я знаю, что есть причина, по которой вы не используете для этого queue или deque. Я просто знаю... Это почему бы и нет до сих пор ускользает от меня. 17.03.2014
  • Требуется использование стека. Сейчас я использую библиотеку, но, вероятно, в конце концов создам свой собственный класс стека. 17.03.2014
  • Нужно ли использовать стек для оба или достаточно только ссылочного параметра? Не то чтобы это обязательно снизит вашу производительность (которую можно значительно улучшить, и я опубликую ответ, если у меня будет шанс). 17.03.2014
  • @WhozCraig Оба? Я не совсем понимаю, что вы имеете ввиду. Вы говорите о простом хранении указателя в стеке? На самом деле я пытаюсь последовать совету пользователя 2445771 и просто использовать строки прямо сейчас. Я обновлю этот код, когда смогу. Я пытаюсь изменить это как можно лучше. 17.03.2014

Ответы:


1

Если я понимаю, что вы пытаетесь сделать правильно, вы хотите, чтобы весь файл вращался XOR с символами в ключе шифрования. Если это так, вы, вероятно, можете устранить свою непосредственную ошибку, просто выполнив следующее:

void readFileEncode(string fileName, stack<char> &text, string cypher)
{
    std::ifstream file(fileName, std::ios::in|std::ios::binary);
    stack<char> temp;
    char ch;

    while (file.get(ch))
        temp.push(ch ^ cypher[temp.size() % cypher.length()]);

    while (!temp.empty())
    {
        text.push(temp.top());
        temp.pop();
    }
}

Наиболее заметными изменениями являются

  • Открытие файла в двоичном режиме с использованием std::ios::in|std::ios::binary для открытого режима. это избавит от необходимости вызывать манипулятор noskipws (который обычно является вызовом функции) для каждого извлеченного символа.
  • Использование file.get(ch) для извлечения следующего символа. Член извлечет следующий символ из файлового буфера напрямую, если он доступен, в противном случае загрузите следующий буфер и повторите попытку.

Альтернативный

Подход «персонаж за персонажем» будет дорогим в любом случае. То, что это проходит через stack<>, за которым будут стоять vector или deque, не принесет вам никакой пользы. То, что он проходит через два из них, лишь усугубляет агонию. Вы также можете загрузить весь файл за один раз, вычислить все XOR напрямую, а затем поместить их в свой стек с помощью обратного итератора:

void readFileEncode
(
    const std::string& fileName,
    std::stack<char> &text,
    const std::string& cypher
)
{
    std::ifstream file(fileName, std::ios::in|std::ios::binary);

    // retrieve file size
    file.seekg(0, std::ios::end);
    std::istream::pos_type pos = file.tellg();
    file.seekg(0, std::ios::beg);

    // early exit on zero-length file.
    if (pos == 0)
        return;

    // make space for a full read
    std::vector<char> temp;
    temp.resize(static_cast<size_t>(pos));
    file.read(temp.data(), pos);

    size_t c_len = cypher.length();
    for (size_t i=0; i<pos; ++i)
        temp[i] ^= cypher[i % c_len];

    for (auto it=temp.rbegin(); it!=temp.rend(); ++it)
        text.push(*it);
}

Вы по-прежнему получаете свой стек на стороне вызывающего абонента, но я думаю, вы будете значительно более довольны производительностью.

17.03.2014
  • Кстати, спасибо, что потратили столько времени, чтобы опубликовать это! 18.03.2014
  • Ваши заметные изменения имеют смысл. Я понимаю, зачем использовать file.get(ch). Однако это решение все еще не работало. Он декодирует первые 10 или около того слов, а все остальное после этого остается тарабарщиной. Не уверен, почему. Я смотрю на это сейчас. Единственная причина, по которой я не буду использовать альтернативный метод, заключается в том, что я не рассмотрел векторы, некоторые функции и другие вещи, которые вы используете. Я хочу иметь возможность полностью понять решение, и я должен сказать, что альтернатива немного выше моего понимания. 18.03.2014
  • Я протестировал оба решения с файлом размером ровно 100 МБ, и результаты оказались именно такими, как я и ожидал. И на самом деле, сброс стека в другой файл и повторение процедуры дает в результате первый файл, что вполне ожидаемо. Я не уверен, в какой цепочке инструментов и системе вы это делаете, но, как написано, оба должны работать. 18.03.2014
  • Отредактировал мой пост. Тогда должно быть что-то в моем главном. Теперь полный код прикреплен к сообщению. Еще раз спасибо, надеюсь, вы сможете указать, чего мне не хватает, потому что я думал, что моя основная задача довольно прямолинейна. Моя цель - адаптировать это к реализации argc и argv. Я просто пытаюсь заставить его работать так, как есть. 18.03.2014
  • Имеет ли значение, какой у меня шифр? Я просто пытаюсь сузить круг. Я использую пятибуквенную работу для своего шифра. 18.03.2014
  • не имеет значения, что это за шифр, если он имеет длину. (т.е. передавать пустую строку было бы нехорошо). Пока вы используете один и тот же симметричный пароль для encr и decr, все должно быть в порядке. 18.03.2014
  • В порядке. Я только что проверил код вашего выходного файла, и вы не должны не использовать оператор вставки потока. используя приведенный выше код, вы должны открывать выходной файл в режиме std::ios::out | std::ios::binary и использовать file.put(text.top());. Попробуйте. 18.03.2014
  • О боже. Так просто. Я слишком долго смотрел на это. Я должен был заметить это, увидев это в функции readFileEncode() в ifstream. Опять же, имеет смысл после того, как вы укажете на то, что находится прямо перед вашим лицом. Хотел бы я иметь твой талант. Спасибо за помощь. Это настраивает меня на правильные классы стека и argc main. Очень признателен. 18.03.2014

  • 2

    просто для информации: никогда не читайте файл char за char, вам потребуются часы, чтобы закончить 100Mb. прочитайте не менее 512 байт (в моем случае я читаю напрямую 1 или 2 МБ ==> сохраняю в char *, а затем обрабатываю).

    17.03.2014
    Новые материалы

    Кластеризация: более глубокий взгляд
    Кластеризация — это метод обучения без учителя, в котором мы пытаемся найти группы в наборе данных на основе некоторых известных или неизвестных свойств, которые могут существовать. Независимо от..

    Как написать эффективное резюме
    Предложения по дизайну и макету, чтобы представить себя профессионально Вам не позвонили на собеседование после того, как вы несколько раз подали заявку на работу своей мечты? У вас может..

    Частный метод Python: улучшение инкапсуляции и безопасности
    Введение Python — универсальный и мощный язык программирования, известный своей простотой и удобством использования. Одной из ключевых особенностей, отличающих Python от других языков, является..

    Как я автоматизирую тестирование с помощью Jest
    Шутка для победы, когда дело касается автоматизации тестирования Одной очень важной частью разработки программного обеспечения является автоматизация тестирования, поскольку она создает..

    Работа с векторными символическими архитектурами, часть 4 (искусственный интеллект)
    Hyperseed: неконтролируемое обучение с векторными символическими архитектурами (arXiv) Автор: Евгений Осипов , Сачин Кахавала , Диланта Хапутантри , Тимал Кемпития , Дасвин Де Сильва ,..

    Понимание расстояния Вассерштейна: мощная метрика в машинном обучении
    В обширной области машинного обучения часто возникает необходимость сравнивать и измерять различия между распределениями вероятностей. Традиционные метрики расстояния, такие как евклидово..

    Обеспечение масштабируемости LLM: облачный анализ с помощью AWS Fargate и Copilot
    В динамичной области искусственного интеллекта все большее распространение получают модели больших языков (LLM). Они жизненно важны для различных приложений, таких как интеллектуальные..