Я начинающий программист. Я создаю библиотеку для обработки двоичных файлов определенного типа - например, кода c (хотя без необходимости обрабатывать прогрессивный поток, поступающий по проводам). Я ищу эффективный способ чтения файла в память и последующего анализа частей данных по мере необходимости. В частности, я хотел бы избежать больших копий памяти, надеюсь, без особой дополнительной сложности, чтобы избежать этого.
В некоторых ситуациях я хочу выполнять последовательное чтение значений в данных. Для этого хорошо работает MemoryStream.
FileStream fs = new FileStream(_fileName, FileMode.Open, FileAccess.Read);
byte[] bytes = new byte[fs.Length];
fs.Read(bytes, 0, bytes.Length);
_ms = new MemoryStream(bytes, 0, bytes.Length, false, true);
fs.Close();
(Это включало копию из массива байтов в поток памяти; это один раз, и я не знаю способа избежать этого.)
С потоком памяти легко найти произвольные позиции, а затем начать чтение элементов структуры. Например,
_ms.Seek(_tableRecord.Offset, SeekOrigin.Begin);
byte[] ab32 = new byte[4];
_version = ConvertToUint(_ms.Read(ab32));
_numRecords = ConvertToUint(_ms.Read(ab32));
// etc.
Но также могут быть случаи, когда я хочу взять срез из памяти, соответствующий какой-то большой структуре, а затем перейти к методу для определенной обработки. MemoryStream этого не поддерживает. Я всегда мог передать MemoryStream плюс смещение и длину, хотя это не всегда могло быть наиболее удобным.
Вместо MemoryStream я мог бы сохранить данные в памяти, используя Memory. Это поддерживает нарезку, но не последовательное чтение.
Если в какой-то ситуации я хочу получить фрагмент (а не передавать поток и смещение / длину), я мог бы построить ArraySegment из MemoryStream.GetBuffer.
ArraySegment<byte> as = new ArraySegment<byte>(ms.GetBuffer(), offset, length);
Мне, однако, не ясно, приведет ли это к (потенциально большой) копии, или если при этом используется ссылка на ту же самую память, содержащуюся в MemoryStream. Я понимаю, что GetBuffer предоставляет доступ к базовой памяти, а не предоставляет копию; и этот ArraySegment будет указывать на ту же самую память?
Будут моменты, когда мне нужно будет получить фрагмент, который является копией, так как мне нужно будет изменить некоторые элементы, а затем обработать это , но без изменения оригинала. Если ArraySegment получает ссылку, а не копию, я полагаю, что мог бы использовать ArraySegment<byte>.ToArray()
?
Итак, мои вопросы: является ли MemoryStream лучшим подходом? Есть ли какой-либо другой тип, который позволяет последовательное чтение, например MemoryStream, но также позволяет нарезать, например Memory?
Если мне нужен фрагмент без копирования памяти, ArraySegment<byte>(ms.GetBuffer(), offset, length)
сделает это?
Тогда, если мне нужно копию, которую можно изменить, не затрагивая оригинал, используйте ArraySegment<byte>.ToArray()
?
Есть ли способ прочитать данные из файла непосредственно в новый MemoryStream без создания временного массива байтов, который копируется?
Лучше ли я к этому подхожу?