45723 (Работа с бинарными данными и реестром Windows на платформе .NET), страница 3

2016-08-02СтудИзба

Описание файла

Документ из архива "Работа с бинарными данными и реестром Windows на платформе .NET", который расположен в категории "". Всё это находится в предмете "информатика" из , которые можно найти в файловом архиве . Не смотря на прямую связь этого архива с , его также можно найти и в других разделах. Архив можно найти в разделе "остальное", в предмете "информатика, программирование" в общих файлах.

Онлайн просмотр документа "45723"

Текст 3 страницы из документа "45723"

Чтобы прочитать данные, сохраненные в потоке System.IO.Stream классом AcedStreamWriter, нужно воспользоваться классом AcedStreamReader. Экземпляр этого класса может быть ассоциирован с потоком типа System.IO.Stream с помощью метода AssignStream. Если данные, помещенные в поток, зашифрованы, при вызове метода AssignStream следует указать ключ шифра в виде значения типа System.Guid. В методе AssignStream сразу считывается длина фрагмента данных, помещенного в поток классом AcedStreamWriter. Это значение возвращается свойством Length класса AcedStreamReader. Длина может быть равна значению -1, если не было возможности сохранить в потоке настоящее значение длины. В экземпляре класса AcedStreamReader также имеется два буфера, каждый размером по 2МБ. Первый предназначен для данных, считанных из потока System.IO.Stream, второй – для распакованных данных. Когда вызывается один из методов Read… класса AcedStreamReader, сначала предпринимается попытка считать значение из буфера распакованных данных. Если достигнут конец буфера, из потока System.IO.Stream считывается следующий фрагмент данных. Для этого фрагмента проверяется значение контрольной суммы Адлера. Затем, если данные зашифрованы, выполняется их дешифрование и проверка цифровой сигнатуры RipeMD-160. Потом, если данные упакованы, производится их распаковка во второй буфер. Теперь значение может быть прочитано и возвращено функцией Read.… При чтении из потока длинных массивов перегруженным методом Read() класса AcedStreamReader возможна ситуация, когда для считывания всего массива приходится несколько раз заполнять внутренний буфер данными из потока System.IO.Stream.

Так как экземпляры классов AcedStreamWriter и AcedStreamReader занимают собой значительный объем памяти (каждый свыше 4МБ), создавать их при каждом чтении из потока нерационально. Сборщик мусора в .NET Framework автоматически относит блоки памяти свыше 85000 байт ко второму поколению (об этом см. в книге Джеффри Рихтера "Программирование на платформе .NET Framework" – M.: Издательско-торговый дом "Русская Редакция", 2003). Такие блоки лучше использовать для ресурсов с длительным временем существования. В противном случае, частое пересоздание больших блоков памяти отрицательно сказывается на общей производительности приложения. Для решения этой проблемы в классах AcedStreamWriter и AcedStreamReader имеется статическое свойство Instance, которое при первом обращении к нему создает экземпляр соответствующего класса, а при следующих обращениях просто возвращает ссылку на существующий экземпляр. Тогда, вместо того, чтобы создавать новые экземпляры классов вызовом соответствующих конструкторов, лучше воспользоваться единственным экземпляром, возвращаемым свойством Instance. Этот подход аналогичен тому, который применяется в классах AcedDeflator и AcedInflator. Чтобы освободить занимаемую память можно вызвать статический метод Release(), освобождающий ссылку на экземпляр соответствующего класса.

После помещения всех данных в поток AcedStreamWriter, а также после чтения необходимых данных из потока AcedStreamReader, нужно вызвать метод Close() для выполнения завершающих действий. Если в параметре closeStream метода Close() передано значение True, поток типа System.IO.Stream, ассоциированный с данным экземпляром класса AcedStreamWriter или AcedStreamReader, закрывается вызовом метода Close() потока.

Классы AcedWriterStream, AcedReaderStream

Эти классы представляют собой оболочку над другими классами, предназначенными для работы с бинарным потоком. Они используются, когда надо представить экземпляры других классов в виде объектов, производных от класса System.IO.Stream.

Класс AcedWriterStream является потомком класса System.IO.Stream и предназначен для записи данных в потоки типа AcedMemoryWriter и AcedStreamWriter. В его конструктор передается ссылка на интерфейс IAcedWriter, который поддерживается классами AcedMemoryWriter и AcedStreamWriter. Класс AcedWriterStream используется только для записи данных в поток, поэтому его свойства CanRead и CanSeek возвращают значение False, а свойство CanWrite – значение True. Вызов методов Write(), WriteByte(), Flush(), Close() перенаправляется соответствующим методам объекта, реализующего интерфейс IAcedWriter. При чтении свойств Length и Position возвращается число байт, помещенное в выходной бинарный поток. Однако, присвоение значения свойству Position или вызов методов Read(), ReadByte(), Seek(), SetLength() приводит к возникновению исключения типа System.NotSupportedException. Свойство Writer класса AcedWriterStream возвращает ссылку на объект, реализующий интерфейс IAcedWriter, которая была передана в конструктор класса при его создании.

Аналогичным образом применяется класс AcedReaderStream, который также является потомком класса System.IO.Stream. Этот класс предназначен для чтения данных из потоков типа AcedMemoryReader и AcedStreamReader, реализующих интерфейс IAcedReader. Класс AcedReaderStream предназначен исключительно для чтения данных, поэтому его свойство CanRead возвращает значение True, а свойства CanWrite и CanSeek возвращают значение False. Вызов методов Read(), ReadByte(), Close() перенаправляется соответствующим методам объекта, реализующего интерфейс IAcedReader. При чтении свойства Position возвращается текущая позиция в потоке относительно начала данных. Свойство Length возвращает общее число байт, которое может быть прочитано из потока. В некоторых случаях количество байт, помещенное в поток, неизвестно. Тогда свойство Length возвращает значение -1. Попытка присвоения значения свойству Position или вызова одного из следующих методов: Seek(), SetLength(), Write(), WriteByte() заканчивается возникновением исключения типа System.NotSupportedException. Свойство Reader класса AcedReaderStream возвращает интерфейс IAcedReader, переданный в конструктор класса. Подробную информацию о свойствах и методах интерфейсов IAcedWriter, IAcedReader можно найти в файле Interfaces.cs исходного кода.

Класс AcedRegistry

AcedRegistry восполняет собой отсутствие в .NET Framework класса, подобного классу TRegistry в Borland Delphi. Его особенностью по сравнению со стандартным классом Microsoft.Win32.Registry является наличие специальных методов для помещения в реестр значений различного типа и для чтения соответствующих значений из реестра. Класс AcedRegistry включает методы для работы с данными, которые представлены значениями следующих типов: String, Byte[], Int32, Boolean, DateTime, Decimal, Double, Guid, Int64.

Работа с классом AcedRegistry начинается с вызова конструктора, который принимает три параметра: первый (registryBaseKey) – выбирает ветвь реестра, такую как HKEY_CURRENT_USER или HKEY_LOCAL_MACHINE; второй параметр (registryKey) указывает наименование ключа реестра, с которым предполагается работать; третий параметр задает режим работы: только чтение или чтение/запись. Если указанный ключ не существует, то при открытии его в режиме "только для чтения" ошибка не возникает. Тогда каждое обращение к функциям Get() для чтения значений ключа вернет False, а при вызове GetDef() будет возвращаться значение по умолчанию. При открытии ключа в режиме, допускающем запись, если он отсутствует, соответствующий ключ немедленно создается в реестре. Обратиться к объекту типа Microsoft.Win32.RegistryKey, представляющему открытый ключ реестра, можно через свойство RegistryKey класса AcedRegistry.

Перегруженный метод Put() предназначен для записи в реестр значений различного типа. Функция Get() считывает значение с указанным именем и сохраняет его в переменной, передаваемой как ref-параметр. Если запрашиваемое значение присутствует в реестре, функция возвращает True. Функция GetDef() отличается от Get() тем, что она возвращает прочитанное значение как результат функции. Если соответствующее значение отсутствует в реестре, GetDef() возвращает значение по умолчанию, которое задается вторым параметром при вызове этой функции.

В конце работы с экземпляром класса AcedRegistry для него обязательно надо вызвать метод Dispose(). При использовании языка C# удобно поместить создание класса AcedRegistry в блок using для гарантированного освобождения unmanaged-ресурсов.

Пример использования класса AcedRegistry:

private const string

DemoRegistryKey = "Software\\AcedUtils.NET\\Demo",

cfgStreamFileName = "StreamFileName",

cfgCompressionMode = "CompressionMode";

private static string _streamFileName = String.Empty;

private static AcedCompressionMode _compressionMode;

private static void LoadConfig()

{

using (AcedRegistry config = new AcedRegistry

(AcedBaseKey.CurrentUser, DemoRegistryKey, false))

{

config.Get(cfgStreamFileName, ref

_streamFileName);

_compressionMode = (AcedCompressionMode)

config.GetDef(cfgCompressionMode, 0);

}

}

private static void SaveConfig()

{

using (AcedRegistry config = new AcedRegistry

(AcedBaseKey.CurrentUser, DemoRegistryKey, true))

{

config.Put(cfgStreamFileName, _streamFileName);

config.Put(cfgCompressionMode, (int)

_compressionMode);

}} }

Данный пример взят из демонстрационного проекта, прилагаемого к статье. Значения статических полей _streamFileName и _compressionMode сохраняются в реестре методом SaveConfig() и считываются из реестра методом LoadConfig(). Тип AcedCompressionMode представляет собой перечисление, которое нужно привести к типу System.Int32, чтобы поместить его в реестр. После чтения из реестра с помощью GetDef() значение должно быть преобразовано обратно к типу AcedCompressionMode.

Описание демонстрационного проектаа

Чтобы проиллюстрировать различные способы работы с бинарными данными с помощью рассмотренных выше классов, разработано небольшое приложение, которое представляет собой примитивный аналог архиватора файлов. Верхняя часть главной формы используется для помещения в бинарный поток данных произвольных файлов. При нажатии на кнопку "Добавить файл" пользователю предлагается выбрать на диске файл, который будет добавлен в поток. После помещения в поток одного или нескольких файлов можно сохранить весь поток на диске в виде одного файла. Причем данные при этом могут быть упакованы и зашифрованы. Чтобы проверить механизм контроля целостности данных, можно немного повредить данные в выходном потоке при сохранении его на диске. Для этого нужно пометить опцию "Инвертировать третий байт". Нижняя часть формы позволяет загрузить данные потока из файла на диске. Если поток зашифрован, перед чтением с диска надо установить опцию "Расшифровывать с паролем" и указать соответствующий пароль в поле ввода. Кроме данных, в бинарном потоке сохраняются имена и размеры файлов, которые отображаются в соответствующем списке после чтения потока с диска. Отдельные файлы из этого списка можно пометить и выгрузить нажатием кнопки "Сохранить отмеченный файл".

Информация об имени файла потока, а также об использованном режиме сжатия сохраняется в реестре с помощью класса AcedRegistry и восстанавливается при следующем запуске программы. При добавлении очередного файла в бинарный поток сначала записывается его имя методом AcedMemoryWriter.WriteString(), потом длина файла в байтах методом AcedMemoryWriter.WriteInt32(), затем в потоке резервируется место для самих данных вызовом AcedMemoryWriter.Skip(). Фактическое заполнение данными происходит при вызове метода FileStream.Read(), в который передается ссылка на внутренний массив экземпляра класса AcedMemoryWriter, возвращаемый функцией GetBuffer(), и смещение, соответствующее длине потока до вызова метода Skip(). При сохранении потока на диске ключ шифрования получается как значение односторонней хеш-функции RipeMD-160 для строки символов, введенной пользователем в качестве пароля. Это значение преобразуется к типу System.Guid вызовом метода AcedRipeMD.ToGuid() и передается в метод ToArray() класса AcedMemoryWriter.

В момент загрузки потока с диска проверяется его контрольная сумма. Затем данные потока расшифровываются и для них проверяется сигнатура RipeMD-160, после чего данные распаковываются. Из потока читаются имена и размеры файлов методами AcedMemoryReader.ReadString() и AcedMemoryReader.ReadInt32(). Для каждого файла вычисляется значение сигнатуры RipeMD-160. Эта информация помещается в список типа ListView. Сами данные пропускаются вызовом метода AcedMemoryReader.Skip(). В свойстве Tag каждого элемента типа ListViewItem списка сохраняется соответствующее ему смещение данных относительно начала потока. Когда пользователь выбрал элемент списка и нажал кнопку "Сохранить отмеченный файл", поток позиционируется на начало методом AcedMemoryReader.Reset(), а затем текущая позиция смещается на число байт, соответствующее значению свойства Tag элемента списка. После создания соответствующего файла на диске, данные выгружаются в файл напрямую из бинарного потока, минуя промежуточные массивы. Для этого в метод FileStream.Write() передается ссылка на внутренний массив экземпляра класса AcedMemoryReader с указанием смещения, равного текущей позиции в потоке.

Свежие статьи
Популярно сейчас
Как Вы думаете, сколько людей до Вас делали точно такое же задание? 99% студентов выполняют точно такие же задания, как и их предшественники год назад. Найдите нужный учебный материал на СтудИзбе!
Ответы на популярные вопросы
Да! Наши авторы собирают и выкладывают те работы, которые сдаются в Вашем учебном заведении ежегодно и уже проверены преподавателями.
Да! У нас любой человек может выложить любую учебную работу и зарабатывать на её продажах! Но каждый учебный материал публикуется только после тщательной проверки администрацией.
Вернём деньги! А если быть более точными, то автору даётся немного времени на исправление, а если не исправит или выйдет время, то вернём деньги в полном объёме!
Да! На равне с готовыми студенческими работами у нас продаются услуги. Цены на услуги видны сразу, то есть Вам нужно только указать параметры и сразу можно оплачивать.
Отзывы студентов
Ставлю 10/10
Все нравится, очень удобный сайт, помогает в учебе. Кроме этого, можно заработать самому, выставляя готовые учебные материалы на продажу здесь. Рейтинги и отзывы на преподавателей очень помогают сориентироваться в начале нового семестра. Спасибо за такую функцию. Ставлю максимальную оценку.
Лучшая платформа для успешной сдачи сессии
Познакомился со СтудИзбой благодаря своему другу, очень нравится интерфейс, количество доступных файлов, цена, в общем, все прекрасно. Даже сам продаю какие-то свои работы.
Студизба ван лав ❤
Очень офигенный сайт для студентов. Много полезных учебных материалов. Пользуюсь студизбой с октября 2021 года. Серьёзных нареканий нет. Хотелось бы, что бы ввели подписочную модель и сделали материалы дешевле 300 рублей в рамках подписки бесплатными.
Отличный сайт
Лично меня всё устраивает - и покупка, и продажа; и цены, и возможность предпросмотра куска файла, и обилие бесплатных файлов (в подборках по авторам, читай, ВУЗам и факультетам). Есть определённые баги, но всё решаемо, да и администраторы реагируют в течение суток.
Маленький отзыв о большом помощнике!
Студизба спасает в те моменты, когда сроки горят, а работ накопилось достаточно. Довольно удобный сайт с простой навигацией и огромным количеством материалов.
Студ. Изба как крупнейший сборник работ для студентов
Тут дофига бывает всего полезного. Печально, что бывают предметы по которым даже одного бесплатного решения нет, но это скорее вопрос к студентам. В остальном всё здорово.
Спасательный островок
Если уже не успеваешь разобраться или застрял на каком-то задание поможет тебе быстро и недорого решить твою проблему.
Всё и так отлично
Всё очень удобно. Особенно круто, что есть система бонусов и можно выводить остатки денег. Очень много качественных бесплатных файлов.
Отзыв о системе "Студизба"
Отличная платформа для распространения работ, востребованных студентами. Хорошо налаженная и качественная работа сайта, огромная база заданий и аудитория.
Отличный помощник
Отличный сайт с кучей полезных файлов, позволяющий найти много методичек / учебников / отзывов о вузах и преподователях.
Отлично помогает студентам в любой момент для решения трудных и незамедлительных задач
Хотелось бы больше конкретной информации о преподавателях. А так в принципе хороший сайт, всегда им пользуюсь и ни разу не было желания прекратить. Хороший сайт для помощи студентам, удобный и приятный интерфейс. Из недостатков можно выделить только отсутствия небольшого количества файлов.
Спасибо за шикарный сайт
Великолепный сайт на котором студент за не большие деньги может найти помощь с дз, проектами курсовыми, лабораторными, а также узнать отзывы на преподавателей и бесплатно скачать пособия.
Популярные преподаватели
Добавляйте материалы
и зарабатывайте!
Продажи идут автоматически
5224
Авторов
на СтудИзбе
428
Средний доход
с одного платного файла
Обучение Подробнее