Помощь в написании студенческих работ
Антистрессовый сервис

Программная реализация утилиты кодирования и декодирования формата BASE 64

КурсоваяПомощь в написанииУзнать стоимостьмоей работы

Как видно из приведенной схемы, проверить установку старшего бита совсем несложно. Если результатом операции получается число 128, значит бит установлен, а если в результате получаем 0, значит старший бит не установлен. Далее в зависимости от полученного результата применим к 6-ти битовому байту битовую операцию OR с числом 1, которая в любом случае применения устанавливает первый (младший) байт… Читать ещё >

Программная реализация утилиты кодирования и декодирования формата BASE 64 (реферат, курсовая, диплом, контрольная)

ФЕДЕРАЛЬНОЕ Государственное АВТОНОМНОЕ образовательное учреждение высшего профессионального образования

БЕЛГОРОДСКИЙ ГОСУДАРСТВЕННЫЙ НАЦИОНАЛЬНЫЙ ИССЛЕДОВАТЕЛЬСКИЙ УНИВЕРСИТЕТ

(НИУ «БелГУ»)

ФАКУЛЬТЕТ КОМПЬЮТЕРНЫХ НАУК И ТЕЛЕКОММУНИКАЦИЙ КАФЕДРА МАТЕМАТИЧЕСКОГО И ПРОГРАММНОГО ОБЕСПЕЧЕНИЯ ИНФОРМАЦИОННЫХ СИСТЕМ

Курсовая работа

Программная реализация ультилиты кодирования и декодирования формата BASE 64

студента дневного отделения 2 курса группы 141 103

Дихтяренко Александра Анатольевича

Научный руководитель:

доцент В.В. Румбешт

БЕЛГОРОД 2013

  • Введение
  • 1. Теоретическая часть
  • 1.1 Что такое кодирования/декодирование формата BASE64, его применение
  • 1.2 Структура BASE64
  • 2. Практическая часть
  • 2.1 Алгоритм кодирования/декодирования
  • 2.2 Реализация программы
  • 2.3 Апробация приложения
  • Заключение
  • Список используемой литературы
  • Приложения

Необходимо разработать утилиту кодирования/декодирования формата BASE64. Разработка ведется в программной среде Linux, используя компилятор gcc. Программа будет писаться на языке С++.

Для того что бы выполнить поставленную задачу необходимо составить план для изучения данной темы и ее реализации, а конкретно:

· Сбор и изучение материалов по теме кодирования/декодирования формата BASE64;

· Разобраться с алгоритмом кодирования/декодирования;

· Реализовать алгоритм, используя полученные знания;

· Сделать вывод из проведенной работы

1. Теоретическая часть

1.1 Что такое кодирования/декодирование формата BASE64, его применение

Дело в том, что изначально для передачи электронной почты в Интернет использовался только текст (RFC822). Затем, с развитием компьютерных технологий, потребовалась возможность передачи нетекстовой информации: аудио, видео, графических файлов, файлов приложений и т. д. Однако почтовые сервера понимают только текст. Именно поэтому появилась необходимость каким-то образом преобразовать двоичный файл в текстовый для этого и был придуман BASE64. Этот способ используется в спецификации MIME.

MIME-это стандарт описания заголовков e-mail сообщений. Используя этот стандарт, в одном письме можно отправить сразу несколько различных вложений. Например, можно положить в письмо архив, видео, картинки или другие файлы. И все это отправить получателю. Почтовая программа-получатель, понимающая MIME, достанет из сообщения все, что было переданно.

Из этого можно сделать вывод, что Base64 — это схема кодирования символьной строки любого набора байт в последовательность только печатных ASCII символов.

утилита кодирование декодирование программный

Рисунок.1.1 ASCII символы

1.2 Структура BASE64

Так как в BASE64 используется алфавит из 64 символов, то для кодировки нам хватит вместо стандартных 8 байт шесть. При этом изменении, мы можем кодировать любые цифры с помощью нашего алфавита.

Преобразование происходит по принципу:

Берутся три последовательных байта по восемь бит (всего 24 бита), и побитно делятся на четыре 6-ти битных байта (всего 24 бита). Замечу, что используется только 6 битов, а 2 остаются «не использованными»

Схематично такое преобразование можно представить:

Рисунок. 1.2 Преобразование в 6 битный вариант

Так кодируется любая информация, но существует еще один важный момент, дело в том, что не обязательно всегда будет 3 байта, именно по этому отсутствующие байты заменяют символом «=»

2. Практическая часть

2.1 Алгоритм кодирования/декодирования

Кодирование Для начала взять 8-ой (старший) бит исходного байта и поместить его в начало 6-ти битового байта. Затем на место 8-го бита исходного байта поместить 7-й бит, а в 6-ти битовом байте первый бит (младший) переместить на место 2-го бита. После такого перемещения освобождается первый (младший) бит 6-ти битного числа. В него и поместим старший (бывший седьмой) бит исходного байта. Затем еще раз пердвинем биты в обоих байтах, после чего повторяем процедуру

Пример:

Рисунок 2.1 Пример

Рассмотрим шаг 1.

Для проверки установки старшего бита исходного 8-ми битного байта наложим на него так называемую «маску». Т. е. применим к нему побитовую операцию AND с числом 128 (10 000 000).

Рисунок 2.2 Наложение «маски-1»

Как видно из приведенной схемы, проверить установку старшего бита совсем несложно. Если результатом операции получается число 128, значит бит установлен, а если в результате получаем 0, значит старший бит не установлен. Далее в зависимости от полученного результата применим к 6-ти битовому байту битовую операцию OR с числом 1, которая в любом случае применения устанавливает первый (младший) байт в 1.

Рисунок 2.3 Наложение «маски-2»

Здесь необходимо учитывать то, что перед применением побитовой операции OR с числом 1 младший бит 6-ти битового байта всегда 0. В случае для первых двух шагов потому, что мы сами обнуляем его при инициализации, для последующих шагов, потому что применяем операцию SHR.

Шаг 2.

Сместим первый бит 6-ти битного байта на вторую позицию, одновременно обнуляя его первый бит. Сместим седьмой байт 8-ми битного байта на 8-е (старшее) место.

Повторяем шаги 1 и 2 шесть раз для каждого бита 6-ти битного байта. Одновременно необходимо следить за тем, что если мы обработали восемь бит байта-источника, следует перейти к новому байту. И последнее — если обработаны все три байта-источники, следует выйти из функции кодирования.

Декодирование

Декодирование ничем не отличается от кодирования. Делаем тоже самое, только источник и приемник меняются местами. Все операции происходят в обратном порядке: проверяем установку первого бита 6-ти битного байта (маску в этом случае надо накладывать с числом 32 (10 000) и в зависимости от результата устанавливаем (или не устанавливаем) младший байт 8-ми битного байта. Затем делаем побитовый сдвиг влево.

После того как мы разобрали весь алгоритм, стоит подготовиться к реализации программы, для этого изобразим блок схемы:

1) Всего алгоритма целиком см. Рисунок.2.4 Блок-схема № 1 (Вся программа в целом)

2) Алгоритм кодирования см. Рисунок.2.5 Блок-схема № 2 (Кодирование)

3) Алгоритм декодирования см. Рисунок.2.6 Блок-схема № 3 (Декодирование)

Рисунок 2.4 Блок-схема № 1 (Вся программа в целом)

Рисунок 2.5 Блок-схема № 2 (Кодирование)

Рисунок 2.6 Блок-схема № 3 (Декодирование)

2.2 Реализация программы

Программа реализована таким образом, что состоит из 3 файлов: kyrsov. cpp;

base64. h;

test. cpp.

Начнем по порядку:

kyrsov. cpp (Созданы функции кодирования/декодирования текста)

Любая программа, написанная на языке программирования С++ прежде всего начинается с подключения заголовочных файлов, или, другими словами, с директив препроцессора (include) Директива препроцессора — это, иными словами, сообщение препроцессору. Нам потребуется всего четыре библиотеки для работы нашей программы

Здесь мы используем директиву include, которая через заголовочные файлы подключает к коду программы необходимые библиотеки. Некоторые заголовочные файлы требуют расширения". h", так как являются более старыми и унаследовали такой стиль подключения от языка-основателя С.

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

Листинг 1.

#include «base64. h» // Написанный в ручную заголовочный файл (описан класс string)

#include // Стандартная директива потокового ввода/вывода

Операции ввода/вывода выполняются с помощью классов istream (потоковый ввод) и ostream (потоковый вывод). Третий класс, iostream, является производным от них и поддерживает двунаправленный ввод/вывод. Для удобства в библиотеке определены три стандартных объекта-потока:

· cin — объект класса istream, соответствующий стандартному вводу. В общем случае он позволяет читать данные с терминала пользователя;

· cout — объект класса ostream, соответствующий стандартному выводу. В общем случае он позволяет выводить данные на терминал пользователя;

· cerr — объект класса ostream, соответствующий стандартному выводу для ошибок. В этот поток мы направляем сообщения об ошибках программы.

Вывод осуществляется, как правило, с помощью перегруженного оператора сдвига влево (<<), а ввод — с помощью оператора сдвига вправо (>>):

Любая программа также должна содержать функции — основную (обязательно) и дополнительные (опционально). В языке С++ содержится два типа функций:

· Функции возвращающие значение;

· Функции, не возвращающие значений.

Для начала рассмотрим пример функции, которая не возвращает значений.

void /*имя функции*/ (/*параметры функции*/) // заголовок функции

Здесь код начинается с зарезервированного слова void — тип данных, который не хранит какие-либо данные. Этот тип данных показывает, что функция не возвращает никаких значений. void никак по-другому не используется и нужен в программе только для того, чтобы компилятор мог определить тип функции. После зарезервированного слова void пишется имя функции за которым ставятся две круглые скобочки, открывающаяся и закрывающаяся. Если функция будет передавать какие-то данные, то внутри круглых скобочек объявляются параметры функции, которые отделяются друг от друга запятыми. Вся эта строка называется заголовком функции, после которого в функции пишутся две фигурные скобочки — внутри которых будет находится алгоритм, называемый телом функции.

Это был пример дополнительной функции, которая значений не возвращает, так как тип ее данных — void.

Далее мы создаем две функции, для кодирования текста и для декодирования текста: base64_encode и base64_decode соответственно.

Разберем их по отдельности.

Листинг 2.

{

string ret;

int i = 0;

int j = 0;

unsigned char char_array3 [3];

unsigned char char_array4 [4];

…}

Здесь мы описываем переменные.

Класс String

Строки — это объекты, которые представляют

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

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

После этого действия, мы циклично модифицируем из 8 битного вида в 6 битный вид нашу строку. Начиная с конца

Листнг 3.

while (in_len—) {

char_array3 [i++] = * (bytes_to_encode++);

if (i == 3) {

char_array4 = (char_array3 & 0xfc) >> 2;

char_array4 = ((char_array3 & 0×03) << 4) + ((char_array3 & 0xf0) >> 4);

char_array4 = ((char_array3 & 0x0f) << 2) + ((char_array3 & 0xc0) >> 6);

char_array4 = char_array3 & 0x3f;

…}

<< - знак побитового смещения

& - знак побитового «и»

Как рассказано и показано в теории здесь специально используется побитовое умножение для проверки установки старших битов с последующим смещение.

Далее повторяется эта же операция, но при условии наличия еще необработанных байтов.

И в конце если не хватает байтов, тоесть их меньше 3, то мы просто заменяем в комбинации отсутствующие байты на знак «=» b дописываем в строку результат.

Листинг 4

while ((i++ < 3))

ret += '=';

}

Вторая функия base64_decode, ведет и состоит аналогично только что описанной, но с измененным порядком действий (в обратном) и поменянными входом и выходом программы местами.

Теперь рассмотрим заголовочный файл base64. h

В нем описан класс стринг

Листинг 6

#include // заголовочный файл подключающий возможности класса string

using namespace std; // подключаемое пространство имен std

string base64_encode (unsigned char const*, unsigned int len); // инициализация функции base64_encode

string base64_decode (string const& s); // инициализация функции base64_encode

Теперь рассмотрим файл test. cpp (Файл в котором задается). Так же как и в первом файле используются подключаемые модули:

Стандартная библиотека ввода/вывода и заголовочный файл «base64. h»

Т.к. в любой программе должна находиться главная функция main, то мы так же ее используем.

При создании нового консольного приложения в языке программирования С++, автоматически создается таккая строка: int main (int argc, char* argv [])

Это — заголовок главной функции main (), в скобочках которого объявлены параметры argс и argv. Так вот, если программу запускать через командную строку, то существует возможность передать какую-либо информацию этой программе через параметры argc и argv []. Первый имеет тип данных int, и содержит количество параметров, передаваемых в функцию main. Причем argc никогда не меньше 1, даже когда мы не передаем никакой информации, потому как первым параметром считается имя функции. Второй параметр — это массив указателей на строки. Через командную строку можно передать только данные строкового типа и именно через параметр argv [] и передается какая-либо информация.

Рисунок 3.1 Схема обьявлений функциив с++

Листинг 7

int main () {

const string s = «kot begit po doroge i myrchit»; // присваиваем переменной s текст который хотели бы закодировать.

string encoded = base64_encode (reinterpret_cast (s. c_str ()), s. length ());

string decoded = base64_decode (encoded);

cout << «encoded: «<< encoded << endl;

cout << «decoded: «<< decoded << endl;

return 0;

}

В этом коде мы присваиваем переменным string, то значение которое получил функции из файла kyrsov. cpp, при этов в функции мы передаем аргументы

После этого воспользовавшись командой вывода cout. Показываем результат на экран

И после возврщаем 0, командой return 0

Так же здесь присутствуют функции для работы с строковыми данными

s. c_str ()

Возвращает указатель на массив, который содержит null-terminated последовательность символов (т.е., C-string), представляющий текущее значение строка объекта. Этот массив включает в себя одну и ту же последовательность символов, составляющих стоимость строка объект плюс дополнительный завершающий null-символ ('') в конце.

s. length ()

Свойство Length возвращает число объектов Char в данном экземпляре, а не число знаков Юникода. Причина в том, что знак Юникода может быть представлен несколькими Char. Для работы с каждым знаком Юникода используйте класс System. Globalization: StringInfo вместо класса Char.

В некоторых языках, таких как C и C++, знак null указывает на конец строки. На платформе.net Framework знак null может быть внедрен в строку. Когда строка включает один или более знаков null, они могут находиться в любом месте строки. Например, в следующей строке подстроки" abc" и «def» разделены знаком null. Свойство Length возвращает значение 7, показывающее, что строка содержит шесть знаков алфавита и знак null.

2.3 Апробация приложения

В данном разделе находятся тестовые данные и отчет о работе приложения.

Скриншот № 1 (Пример работы1)

Скриншот № 2 (Пример работы2)

Так как выполнялся запуск программы на операционной системе Linux, то и компилирование и сборка происходит с помощью консоля.

1 команда. g++ - c kyrsov. cpp test. cpp

Команда благодаря ключу — с создает 2 отдельных объектных файла, заголовочный файл base64. h, разместим в том же каталоге, что и другие файлы, его мы подключили внутри программы.

2 команда. g++ kyrsov. o test. o — o result

Команда собирает вместе 2 объектных файла и создает файл запуск для нашей программы.

3 команда. /result

Эта команда запускает нашу программу, после чего мы видим результат на наших скриншотах

На апробации выяснилось, что программа рабочая, выводы верны, декодирование и кодирование прошли успешно

Заключение

В ходе данной курсовой работы были изучены различные аспекты языка программирования С++. Так же был разобран алгоритм кодирования декодирования формата BASE64 и после чего реализован.

Апробация прошла успешно, скриншоты это подтверждают.

Для себя же, я улучшил свои знания и владения языком С++. Конкретно, работа с классом типа string и функциями, разобрался в компиляции и сборке программы состоящей из нескольких файлов. Научился создавать собственные заголовочные файлы и включать их в программу.

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

Список используемой литературы

1. Холзнер С. Visual C++6: Учебный курс — СПб: Питер, 2001. — 576 с.

2. Андрей Александреску, Современное проектирование на С++ - СПб.: Вильямс, 2002. — 335с.

3. Брюс Эккель, Философия С++ - К.: Питер, 2004, — 575с.

4. Е. Л. Романов, Практикум по программированию на С++. СПб: БВХ-Петербург, 2004. — 425 с.

5. Страуструп Б. Программирование: принципы и практика использования C++, исправленное издание = Programming: Principles and Practice Using C++. — М.: «Вильямс», 2011. — С.1248. — ISBN 978−5-8459−1705−8

6. http://www.cppstudio.com/obuchenie_cpp

7. Р. Лафоре, Объектно-ориентированное программирование в С++. К.: Питер, 2004, — 920с.

8. http://brucha.ru/category/spp/

Приложения

Приложение 1. Программная реализация ультилиты кодирования декодирования формата Base64

1) kyrsov. cpp

#include «base64. h»

#include

using namespace std;

// Использование 64 ьитного алфавита base64

static const string base64_chars = «ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/» ;

// Проверка вводимых значений

static inline bool is_base64 (unsigned char c)

return (isalnum (c)

// Кодирум наш текст

string base64_encode (unsigned char const* bytes_to_encode, unsigned int in_len) {

string ret;

int i = 0;

int j = 0;

unsigned char char_array3 [3];

unsigned char char_array4 [4];

// Запускаем цикл в котором выбираем по 3 байта и модифицируем их, как бы из 8 битного байта в 6 битный байт

while (in_len—) {

char_array3 [i++] = * (bytes_to_encode++);

if (i == 3) {

char_array4 = (char_array3 & 0xfc) >> 2;

char_array4 = ((char_array3 & 0×03) << 4) + ((char_array3 & 0xf0) >> 4);

char_array4 = ((char_array3 & 0x0f) << 2) + ((char_array3 & 0xc0) >> 6);

char_array4 = char_array3 & 0x3f;

// То что получилось запишем в переменную ret

for (i = 0; (i <4); i++)

ret += base64_chars [char_array4 [i]];

i = 0;

}

}

// Продолжаем, если отправили не пустое сообщение

if (i)

{

for (j = i; j < 3; j++)

// лобавляем в конце ноль, что бы сделать сишную строку

char_array3 [j] = '';

char_array4 = (char_array3 & 0xfc) >> 2;

char_array4 = ((char_array3 & 0×03) << 4) + ((char_array3 & 0xf0) >> 4);

char_array4 = ((char_array3 & 0x0f) << 2) + ((char_array3 & 0xc0) >> 6);

char_array4 = char_array3 & 0x3f;

for (j = 0; (j < i + 1); j++)

ret += base64_chars [char_array4 [j]];

// Если байтов меньше 3, то вместо них записывается знак «=», сколько отсутствует столько и «=»

while ((i++ < 3))

ret += '=';

}

return ret;

}

string base64_decode (string const& encoded_string) {

int in_len = encoded_string. size ();

int i = 0;

int j = 0;

int in_ = 0;

unsigned char char_array4 [4], char_array3 [3];

string ret;

// берем наш закодированную строку, идем обратном порядке и смотрим наличи пустых байтов

while (in_len — && (encoded_string [in_]! = '=') && is_base64 (encoded_string [in_])) {

char_array4 [i++] = encoded_string [in_]; in_++;

// аналогичные действия в обратном порядке

if (i ==4) {

for (i = 0; i <4; i++)

char_array4 [i] = base64_chars. find (char_array4 [i]);

char_array3 = (char_array4 << 2) + ((char_array4 & 0×30) >> 4);

char_array3 = ((char_array4 & 0xf) << 4) + ((char_array4 & 0x3c) >> 2);

char_array3 = ((char_array4 & 0×3) << 6) + char_array4 [3];

for (i = 0; (i < 3); i++)

ret += char_array3 [i];

i = 0;

}

}

if (i) {

for (j = i; j <4; j++)

char_array4 [j] = 0;

for (j = 0; j <4; j++)

char_array4 [j] = base64_chars. find (char_array4 [j]);

char_array3 = (char_array4 << 2) + ((char_array4 & 0×30) >> 4);

char_array3 = ((char_array4 & 0xf) << 4) + ((char_array4 & 0x3c) >> 2);

char_array3 = ((char_array4 & 0×3) << 6) + char_array4 [3];

for (j = 0; (j < i — 1); j++) ret += char_array3 [j];

}

return ret;

}

2) base64. h

#include

using namespace std;

string base64_encode (unsigned char const*, unsigned int len);

string base64_decode (string const& s);

3) test. cpp

#include «base64. h»

#include

using namespace std;

int main () {

const string s = «kot begit po doroge i myrchit» ;

string encoded = base64_encode (reinterpret_cast (s. c_str ()), s. length ());

string decoded = base64_decode (encoded);

cout << «encoded: «<< encoded << endl;

cout << «decoded: «<< decoded << endl;

return 0;

}

Программная реализация утилиты кодирования декодирования формата Base64

Показать весь текст
Заполнить форму текущей работой