Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Текст программы.docx
Скачиваний:
0
Добавлен:
01.05.2025
Размер:
102.68 Кб
Скачать

ByteMixer.Cs

using System;

using System.Threading.Tasks;

namespace VStepanov.CourseWork.First.Binary

{

    /// <summary>

    /// Статический класс, содержащий методы для "примешивания" и экстракции произвольных данных из исходных.

    /// </summary>

    public static class ByteMixer

    {

        /// <summary>

        /// Размещает данные сообщения в исходных данных, используя 

        /// указанное число последних бит исходных данных для изменения.

        /// </summary>

        /// <param name="originalData">Исходные данные.</param>

        /// <param name="dataToMix">Данные, которые необходимо примешать.</param>

        /// <param name="nLastBitsUsing">Число последних бит, используемых для записи сообщения.</param>

        /// <returns>Исходные данные, последние биты которых содержат данные сообщения.</returns>

        /// <exception cref="ArgumentException">Возникает при недостатке исходных данных для записи в них сообщения.</exception>

        public static byte[] MixDataIntoBytes(byte[] originalData, byte[] dataToMix, int nLastBitsUsing)

        {

            byte[] relocatedData = Relocator.Split(dataToMix, nLastBitsUsing);

            byte[] mixedData = (byte[])originalData.Clone();

            if (mixedData.Length < relocatedData.Length)

            {

                throw new ArgumentException("Исходных данных не хватает для размещения переданного сообщения.\n");

            }

            byte ereaser = (byte)~((1 << nLastBitsUsing) - 1);

            Parallel.For(0, mixedData.Length, i =>

            {

                mixedData[i] &= ereaser;

                mixedData[i] |= relocatedData[i];

            });

            

            return mixedData;

        }

        /// <summary>

        /// Извлекает сообщение из указанного числа последних бит исходных данных.

        /// </summary>

        /// <param name="container">Исходные данные, содержащие сообщение.</param>

        /// <param name="nLastBitsUsing">Число последних бит, используемых для записи сообщения.</param>

        /// <returns>Сообщение, извлечённое из последних бит исходных данных.</returns>

        public static byte[] ExtractDataFromBytes(byte[] container, int nLastBitsUsing)

        {

            int parts = CommonMethods.GetPartsCount(nLastBitsUsing);

            byte[] clearData = (byte[])container.Clone();

            byte ereaser = (byte)((1 << nLastBitsUsing) - 1);

            Parallel.For(0, clearData.Length, i => clearData[i] &= ereaser);

            return Relocator.Join(clearData, nLastBitsUsing);

        }

    }

}

Relocator.Cs

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Threading.Tasks;

namespace VStepanov.CourseWork.First.Binary

{

    /// <summary>

    /// Статический класс, содержащий методы для перераспледеления бит в байтах.

    /// </summary>

    public static class Relocator

    {

        /// <summary>

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

        /// соответствующее заданному количеству используемых последних бит,

        /// и смещает каждый полученный фрагмент в младшие биты.

        /// </summary>

        /// <param name="bytes">Исходный массив байт.</param>

        /// <param name="nLastBitsUsing">Число используемых последних бит в каждом байте.</param>

        /// <returns>Массив байт, содержащий разбитые и сдвинутые исходные байты.</returns>

        public static byte[] Split(byte[] bytes, int nLastBitsUsing)

        {

            int parts = CommonMethods.GetPartsCount(nLastBitsUsing);

            byte[] res = new byte[bytes.Length * parts];

            Action<int> splitByte = i =>

            {

                byte b = bytes[i];

                for (int j = 0; j < parts; j++)

                {

                    res[i * parts + j] = (byte)(b & ((1 << nLastBitsUsing) - 1));

                    b >>= nLastBitsUsing;

                }

            };

            Parallel.For(0, bytes.Length, splitByte);

            return res;

        }

        /// <summary>

        /// Производит операцию, обратную к производимой методом <see cref="Split"/>.

        /// </summary>

        /// <param name="bytes">Массив разбитых на части и смещённых байт.</param>

        /// <param name="nLastBitsUsing">Число используемых последних бит в каждом байте.</param>

        /// <returns>Массив байт, содержащий "собранные обратно" байты из переданного массива.</returns>

        public static byte[] Join(byte[] bytes, int nLastBitsUsing)

        {

            int parts = CommonMethods.GetPartsCount(nLastBitsUsing);

            if (bytes.Length % parts != 0)

            {

                throw new ArgumentException("Возможно, часть данных была утеряна");

            }

            byte[] res = new byte[bytes.Length / parts];

            Action<int> joinByte = i =>

            {

                for (int j = 0; j < parts; j++)

                {

                    res[i] |= (byte)(bytes[i * parts + j] << (j * nLastBitsUsing));

                }

            };

            Parallel.For(0, res.Length, joinByte);

            return res;

        }

    }

}