MemoryStream
The MemoryStream creates a stream whose backing store is memory. Actually, it represents a pure, in-memory stream of data. Memory is much faster when compared to disk or network accesses.
The following section explains :
# MemoryStream to String
MemoryStream to FileStream
With MemoryStream, you can act upon the byte[] stored in memory rather than a file or other resource. Use a byte[] because it is a fixed sized object making it easier for memory allocation and cleanup and holds relatively no overhead, especially since you don’t need to use the functions of the MemoryStream.
Save Stream to File
C# MemoryStream to a file
using System; using System.Text; using System.Windows.Forms; using System.IO; namespace WindowsFormsApplication2 { public partial class Form1 : Form { public Form1() { InitializeComponent(); } private void button1_Click(object sender, EventArgs e) { string memString = "Memory test string !!"; // convert string to stream byte[] buffer = Encoding.ASCII.GetBytes(memString); MemoryStream ms = new MemoryStream(buffer); //write to file FileStream file = new FileStream("d:\\file.txt", FileMode.Create, FileAccess.Write); ms.WriteTo(file); file.Close(); ms.Close(); } } }
Imports System.IO Imports System.Text Public Class Form1 Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click Dim memString As String = "Memory test string !!!" ' convert string to stream Dim buffer As Byte() = Encoding.ASCII.GetBytes(memString) Dim ms As New MemoryStream(buffer) 'write to file Dim file As New FileStream("d:\file.txt", FileMode.Create, FileAccess.Write) ms.WriteTo(file) file.Close() ms.Close() End Sub End Class
Features
- The semantics are close to the original implementation, and is intended to be a drop-in replacement as much as possible.
- Rather than pooling the streams themselves, the underlying buffers are pooled. This allows you to use the simple pattern to release the buffers back to the pool, as well as detect invalid usage patterns (such as reusing a stream after it’s been disposed).
- is thread-safe (streams themselves are inherently NOT thread safe).
- Implementation of .
- Support for enormous streams through abstracted buffer chaining.
- Extensive support for newer memory-related types like , , , and .
- Each stream can be tagged with an identifying string that is used in logging — helpful when finding bugs and memory leaks relating to incorrect pool use.
- Debug features like recording the call stack of the stream allocation to track down pool leaks
- Maximum free pool size to handle spikes in usage without using too much memory.
- Flexible and adjustable limits to the pooling algorithm.
- Metrics tracking and events so that you can see the impact on the system.
Definition
- Namespace:
- System.IO
- Assembly:
- System.IO.dll
- Assembly:
- System.Runtime.dll
- Assembly:
- System.Runtime.Extensions.dll
- Assembly:
- mscorlib.dll
- Assembly:
- netstandard.dll
Important
Some information relates to prerelease product that may be substantially modified before it’s released. Microsoft makes no warranties, express or implied, with respect to the information provided here.
Creates a stream whose backing store is memory.
In this article
- Inheritance
-
Object
Stream
MemoryStream
- Inheritance
-
Object
MarshalByRefObject
Stream
MemoryStream
- Attributes
-
SerializableAttribute
ComVisibleAttribute
Свойства
Возвращает значение, определяющее в текущем потоке наличие поддержки операций чтения. |
|
Возвращает значение, определяющее в текущем потоке наличие поддержки операций поиска. |
|
Возвращает значение, которое показывает, может ли для данного потока истечь время ожидания. (Унаследовано от Stream) |
|
Возвращает значение, определяющее в текущем потоке наличие поддержки операций записи. |
|
Возвращает или задает число байтов, выделенных для этого потока. |
|
Получает длину потока в байтах. |
|
Возвращает или задает текущее положение в потоке. |
|
Возвращает или задает значение в миллисекундах, определяющее период времени, отведенного потоку на выполнение операции чтения. (Унаследовано от Stream) |
|
Возвращает или задает значение в миллисекундах, определяющее период времени, отведенного потоку на выполнение операции записи. (Унаследовано от Stream) |
Definition
- Namespace:
- System.IO
- Assembly:
- System.IO.dll
- Assembly:
- System.Runtime.dll
- Assembly:
- System.Runtime.Extensions.dll
- Assembly:
- mscorlib.dll
- Assembly:
- netstandard.dll
Important
Some information relates to prerelease product that may be substantially modified before it’s released. Microsoft makes no warranties, express or implied, with respect to the information provided here.
Creates a stream whose backing store is memory.
In this article
- Inheritance
-
Object
Stream
MemoryStream
- Inheritance
-
Object
MarshalByRefObject
Stream
MemoryStream
- Attributes
-
SerializableAttribute
ComVisibleAttribute
Properties
Gets a value indicating whether the current stream supports reading. |
|
Gets a value indicating whether the current stream supports seeking. |
|
Gets a value that determines whether the current stream can time out. (Inherited from Stream) |
|
Gets a value indicating whether the current stream supports writing. |
|
Gets or sets the number of bytes allocated for this stream. |
|
Gets the length of the stream in bytes. |
|
Gets or sets the current position within the stream. |
|
Gets or sets a value, in milliseconds, that determines how long the stream will attempt to read before timing out. (Inherited from Stream) |
|
Gets or sets a value, in milliseconds, that determines how long the stream will attempt to write before timing out. (Inherited from Stream) |
Save MemoryStream to a String
The following program shows how to Read from memorystream to a string. Steps follows..
StreamWriter sw = new StreamWriter(memoryStream); sw.WriteLine("Your string to Memoery");
This string is currently saved in the StreamWriters buffer. Flushing the stream will force the string whose backing store is memory (MemoryStream).
How do you get a string from a MemoryStream
Next step is to read this string from memorystream.
ms.Position = 0; StreamReader sr = new StreamReader(ms); string myStr = sr.ReadToEnd();
The StreamReader will read from the current position of the MemoryStream which is currently set at the end of the string earlier we just wrote to it. We have to set the position to 0 in order to read from the start.
Save MemoryStream to a String — C#
using System; using System.Windows.Forms; using System.IO; namespace WindowsFormsApplication1 { public partial class Form1 : Form { public Form1() { InitializeComponent(); } private void button1_Click(object sender, EventArgs e) { using (MemoryStream ms = new MemoryStream()) { StreamWriter sw = new StreamWriter(ms); sw.WriteLine("Hello World !!"); sw.Flush(); ms.Position = 0; StreamReader sr = new StreamReader(ms); string myStr = sr.ReadToEnd(); MessageBox.Show(myStr); } } } }
Save MemoryStream to a String — VB.Net
Imports System.IO Public Class Form1 Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click Using ms As New MemoryStream() Dim sw As New StreamWriter(ms) sw.WriteLine("Hello World !!") sw.Flush() ms.Position = 0 Dim sr As New StreamReader(ms) Dim myStr As String = sr.ReadToEnd() MessageBox.Show(myStr) End Using End Sub End Class
There is another methos also help us to read from Memory stream.
Владельцы, объекты-получатели и управление жизненным циклом
Так как буферы можно передавать от API к API, а доступ к буферам иногда может осуществляться из нескольких потоков, необходимо управлять временем их существования. Есть три важных момента:
-
Владение. Владелец экземпляра буфера отвечает за управление его жизненным циклом, включая удаление буфера, который больше не используется. У буфера может быть только один владелец. Владельцем обычно является компонент, который создал буфер или получил его из фабрики. Право владения можно передавать. Компонент А может передать контроль над буфером компоненту Б, после чего компонент А больше не сможет использовать буфер, а компонент Б будет отвечать за удаление буфера, когда необходимость в нем исчезнет.
-
Использование. Объект-получатель экземпляра буфера может выполнять чтение и запись в буфер. У буфера одновременно может быть только один объект-получатель, если не обеспечен какой-либо внешний механизм синхронизации. Активным объектом-получателем буфера необязательно является владелец буфера.
-
Аренда. Аренда — это срок, в течение которого определенный компонент может быть объектом-получателем буфера.
Следующий пример псевдокода иллюстрирует три этих понятия. Он содержит метод , который создает буфер Memory<T> типа Char, вызывает метод для записи строкового представления целого числа в буфер, а затем вызывает метод для отображения значения буфера.
Метод создает буфер (в этом случае экземпляр Span<T>), поэтому он является его владельцем. Таким образом, отвечает за удаление буфера, когда он больше не используется. Он выполняет это путем вызова метода буфера . (Здесь метод по сути очищает память буфера. У структуры Span<T> нет метода для удаления буфера.)
У буфера два объекта-получателя — и . Одновременно у буфера может быть только один объект-получатель (сначала , а затем ), и ни один из них не является владельцем буфера
Обратите внимание, что объект-получатель здесь имеет не только возможность чтения из буфера. Объекты-получатели могут изменять содержимое буфера, как в случае , если предоставлены соответствующие права
Метод арендует буфер (может быть его объектом-получателем), начиная с вызова метода и до момента его возвращения. Аналогичным образом арендует буфер на время своего выполнения, и аренда заканчивается, когда выполнение завершается. (Не существует API для управления арендой, так как аренда — концептуальное понятие.)
События
Changed |
Происходит, когда изменяется класс Freezable или объект, который входит в его состав. (Унаследовано от Freezable) |
DecodeFailed |
Происходит при неудаче загрузки изображения вследствие повреждения его заголовка. (Унаследовано от BitmapSource) |
DownloadCompleted |
Происходит при полном завершении загрузки содержимого точечного рисунка. (Унаследовано от BitmapSource) |
DownloadFailed |
Происходит при невозможности загрузки содержимого точечного рисунка. (Унаследовано от BitmapSource) |
DownloadProgress |
Происходит при изменении состояния хода загрузки содержимого точечного рисунка. (Унаследовано от BitmapSource) |
Extension Methods
Converts a managed stream in the .NET for Windows Store apps to an input stream in the Windows Runtime. |
|
Converts a managed stream in the .NET for Windows Store apps to an output stream in the Windows Runtime. |
|
Converts the specified stream to a random access stream. |
|
Returns a Windows.Storage.Streams.IBuffer interface that represents the same memory as the specified memory stream. |
|
Returns a Windows.Storage.Streams.IBuffer interface that represents a region within the memory that the specified memory stream represents. |
|
Configures how awaits on the tasks returned from an async disposable are performed. |
Как исправить ошибку «Out of memory»
Для решения указанной проблемы рекомендую сделать следующее:
- Перезагрузите ваш ПК, и запустите требуемую программу вновь. Возможно, что проблема имеет случайный характер, и более повторяться не будет;
- Перед запуском нужной программы закройте другие ненужные программы (браузер, музыкальный или видео плеер, текстовый или графический редактор, мессенджер и так далее);
- Если проблема возникает во время серфинга в сети, закройте всё множество вкладок вашего браузера (при наличии), оставив лишь одну или две.
Альтернативным вариантом решения проблемы является установка соответствующего фикса от Майкрософт. Или использование расширений или дополнений для браузера уровня «The Great Suspender» для «Google Chrome», хорошо работающего с ненужными вкладками браузера.
- Добавьте оперативной памяти на ваш ПК. Если у вас на компьютере установлено 1-2 гигабайта памяти, будет оптимальным довести её объём до 4 гигабайт (а для 64-битных Виндовс 7, 8 и 10 версии рекомендую 8 и более гигабайт);
- Убедитесь, что на вашем жёстком диске (или SSD) достаточно свободного места. При необходимости, освободите диск от ненужных файлов;
- Используйте инструмент командной строки BCDEdit для изменения параметров загрузки системы. Если у вас на ПК установлена Виндовс 7 и более, запустите командную строку от имени администратора на Виндовс 7 и Виндовс 10, и в ней наберите:
bcdedit/set IncreaseUserVa 3072
И нажмите на ввод, и перезагрузите ваш ПК. Функционал данной команды позволяет выделить пользовательским приложениям 3 гигабайта оперативной памяти для работы. В некоторых системах этого может быть слишком много, потому если после ввода данной команды система начала чаще сбоить, то введите в командной строке от имени администратора:
bcdedit /set IncreaseUserVa 2560 —что позволит задействовать 2,5 гигабайта вместо ранее забронированных 3.
Если ситуацию этим исправить не удалось, верните настройки на состояние по умолчанию:
bcdedit /deletevalue IncreaseUserVa
-
Увеличьте объём файла подкачки. Нажмите кнопку «Пуск», в строке поиска введите sysdm.cpl и нажмите ввод. В открывшемся окне настроек системы выберите «Дополнительно» — «Быстродействие» — «Параметры» — «Дополнительно» — «Виртуальная память» — «Изменить». Снимите галочку с опции автоматического размера, поставьте галочку на «Указать размер», и поставьте исходный размер в 8192, и максимальный в 8192. Затем выберите «Задать»;
- Если ошибка возникает при использовании игровой программы, перейдите в её графические настройки, и выберите их минимальные значения;
- Произведите правильную настройку «Java». Для решения проблем с игровой программой «Майнкрафт» перейдите в Панель управления Виндовс, найдите там «Java» и запустите данную среду исполнения. Нажмите на кнопку «View», затем дважды кликните на «Runtime Parametres». Введите туда –Xms256m – Xmx3072m (или больше). Xms – это минимальное выделение ОЗУ, Xmx – максимальное. Значение Xmx рекомендуют устанавливать на процентов 70-80% от общего объёма ОЗУ. Примените изменения, и перезагрузите ваш ПК.
Encoding.ASCII.GetString(ms.ToArray());
C# Source Code
using System; using System.Windows.Forms; using System.IO; namespace WindowsFormsApplication1 { public partial class Form1 : Form { public Form1() { InitializeComponent(); } private void button1_Click(object sender, EventArgs e) { using (MemoryStream ms = new MemoryStream()) { StreamWriter sw = new StreamWriter(ms); sw.WriteLine("Hello World !!!"); sw.Flush(); string myStr = Encoding.ASCII.GetString(ms.ToArray ()); MessageBox.Show(myStr); } } } }
VB.Net Source Code
Imports System.IO Imports System.Text Public Class Form1 Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click Using ms As New MemoryStream() Dim sw As New StreamWriter(ms) sw.WriteLine("Hello World !!!") sw.Flush() Dim myStr As String = Encoding.ASCII.GetString(ms.ToArray()) MessageBox.Show(myStr) End Using End Sub End Class
NEXT…..Parse XML — XmlReader
Some simple examples using built-in types
Say you have a method that needs to use a temporary buffer, but you don’t want to incur the cost of an allocation. One way to write this code is to use the existing type.
// workhorse method static void DoSomething(Memory<byte> scratchBuffer); public void UserCode() { byte[] rentedArray = ArrayPool<byte>.Shared.Rent(...); try { DoSomething(rentedArray); // T[] implicitly converted to Memory<T> } finally { if (rentedArray != null) { ArrayPool<byte>.Shared.Return(rentedArray); } } }
The above method is almost always allocation-free. When the method is finished with the buffer, the buffer is returned back to the shared .
This method can be replaced with the following simpler code, using instead of .
// workhorse method static void DoSomething(Memory<byte> scratchBuffer); public void UserCode() { using (var rental = MemoryPool<byte>.Shared.Rent(...)) { DoSomething(rental.Memory); } }
In fact, you could even abstract away the particular used by this method, allowing the application to use a custom memory pool that is backed by native memory or some other custom implementation.
// workhorse method static void DoSomething(Memory<byte> scratchBuffer); public void UserClass : IDisposable { private readonly MemoryPool<T> _pool; public UserClass(MemoryPool<T> pool) { _pool = pool; } public void UserCode() { using (var rental = pool.Rent(...)) { DoSomething(rental.Memory); } } void IDisposable.Dispose() { _pool.Dispose(); } }
Remarks
The current position of a stream is the position at which the next read or write operation could take place. The current position can be retrieved or set through the Seek method. When a new instance of MemoryStream is created, the current position is set to zero.
Note
This type implements the IDisposable interface, but does not actually have any resources to dispose. This means that disposing it by directly calling or by using a language construct such as (in C#) or (in Visual Basic) is not necessary.
Memory streams created with an unsigned byte array provide a non-resizable stream of the data. When using a byte array, you can neither append to nor shrink the stream, although you might be able to modify the existing contents depending on the parameters passed into the constructor. Empty memory streams are resizable, and can be written to and read from.
If a MemoryStream object is added to a ResX file or a .resources file, call the GetStream method at runtime to retrieve it.
If a MemoryStream object is serialized to a resource file it will actually be serialized as an UnmanagedMemoryStream. This behavior provides better performance, as well as the ability to get a pointer to the data directly, without having to go through Stream methods.
Определение
- Пространство имен:
- System.IO
- Сборки:
- mscorlib.dll, System.IO.UnmanagedMemoryStream.dll
- Сборка:
- System.Runtime.dll
- Сборка:
- System.IO.UnmanagedMemoryStream.dll
- Сборка:
- System.Runtime.InteropServices.dll
- Сборка:
- mscorlib.dll
- Сборка:
- netstandard.dll
Важно!
Некоторые сведения относятся к предварительной версии продукта, в которую до выпуска могут быть внесены существенные изменения. Майкрософт не предоставляет никаких гарантий, явных или подразумеваемых, относительно приведенных здесь сведений.
Важно!
Этот API несовместим с CLS.
Предоставляет доступ к неуправляемым блокам памяти из управляемого кода.
В этой статье
- Наследование
-
Object
Stream
UnmanagedMemoryStream
- Наследование
-
Object
MarshalByRefObject
Stream
UnmanagedMemoryStream
- Производный
- Атрибуты
Свойства
Получает или задает значение, представляющее базовый Uri текущего контекста BitmapImage. |
|
Получает или задает BitmapCacheOption для использования данным экземпляром BitmapImage. |
|
Возвращает значение, которое указывает, можно ли сделать объект неизменяемым. (Унаследовано от Freezable) |
|
Возвращает или задает BitmapCreateOptions для BitmapImage. |
|
Возвращает или задает высоту декодированного изображения в пикселях. |
|
Возвращает или задает ширину декодированного изображения в пикселях. |
|
Возвращает объект DependencyObjectType , который заключает в оболочку тип CLR данного экземпляра. (Унаследовано от DependencyObject) |
|
Возвращает объект Dispatcher, с которым связан этот объект DispatcherObject. (Унаследовано от DispatcherObject) |
|
Возвращает горизонтальные точки на дюйм изображения (DPI). (Унаследовано от BitmapSource) |
|
Получает вертикальные точки на дюйм изображения (DPI). (Унаследовано от BitmapSource) |
|
Возвращает исходный формат PixelFormat данных растрового изображения. (Унаследовано от BitmapSource) |
|
Возвращает значение, которое указывает, сопоставлены ли один или несколько объектов AnimationClock любому из свойств зависимостей этого объекта. (Унаследовано от Animatable) |
|
Возвращает высоту исходного растрового изображения в единицах, не зависящих от устройства (1/1/96 дюйма на единицу). (Унаследовано от BitmapSource) |
|
Получает значение, указывающее, производит ли BitmapImage в данный момент загрузку содержимого. |
|
Получает значение, указывающее, доступен ли объект для изменения в настоящее время. (Унаследовано от Freezable) |
|
Получает значение, указывающее, является ли этот экземпляр в данный момент запечатанным (доступным только для чтения). (Унаследовано от DependencyObject) |
|
Не поддерживается. BitmapImage не поддерживает свойство и создает исключение NotSupportedException. |
|
Получает цветовую палитру растрового изображения, если она задана. (Унаследовано от BitmapSource) |
|
Получает высоту растрового изображения в пикселях. (Унаследовано от BitmapSource) |
|
Получает ширину растрового изображения в пикселях. (Унаследовано от BitmapSource) |
|
Получает или задает угол для поворота BitmapImage. |
|
Получает или задает прямоугольник, который используется в качестве источника для BitmapImage. |
|
Получает или задает исходный поток BitmapImage. |
|
Получает или задает значение, представляющее текущую политику кэширования изображений из источника HTTP. |
|
Получает или задает источник Uri для BitmapImage. |
|
Возвращает ширину точечного рисунка в единицах, независимых от устройства (1/1/96 дюйма на единицу). (Унаследовано от BitmapSource) |
MemoryT> и модель «владелец — объект-получатель»
Как уже сообщалось в разделе , у буфера всегда есть владелец. В .NET Core поддерживаются две модели владения:
-
Модель с единственным владельцем. У буфера есть только один владелец в течение всего его времени существования.
-
Модель, позволяющая передавать право владения. Право владения буфером может передаваться от его первоначального владельца (его создателя) другому компоненту, после чего последний отвечает за управление временем существования буфера. Новый владелец может, в свою очередь, передать право владения другому компоненту и так далее.
С помощью интерфейса System.Buffers.IMemoryOwner<T> можно явно управлять правом владения буфером. IMemoryOwner<T> поддерживает обе модели владения. Владельцем буфера является компонент, на который ссылается IMemoryOwner<T>. В следующем примере используется экземпляр IMemoryOwner<T> для указания владельца буфера Memory<T>.
Этот пример можно также написать, используя .
В этом коде:
-
Экземпляр IMemoryOwner<T> ссылается на метод , поэтому метод является владельцем буфера.
-
Методы и принимают Memory<T> как общедоступный API-интерфейс. Таким образом, они являются объектами-получателями буфера, выступая в этой роли поочередно.
При этом метод позволяет выполнить запись значения в буфер, а метод — нет. Чтобы отобразить этот факт, последний мог бы принять аргумент типа ReadOnlyMemory<T>. Дополнительные сведения о ReadOnlyMemory<T> см. в разделе .
Экземпляры Memory<T> без владельца
Можно создать экземпляр Memory<T>, не используя IMemoryOwner<T>. В этом случае владелец буфера указывается неявно, поэтому поддерживается только модель с единственным владельцем. Выполнить это можно следующим образом:
-
Вызвав один из конструкторов Memory<T> и передав , как показано в следующем примере.
-
Вызвав метод расширения для создания экземпляра .
Метод, который первоначально создает экземпляр Memory<T>, является неявным владельцем буфера. Право владения нельзя передать другому компоненту, так как отсутствует экземпляр IMemoryOwner<T>, позволяющий такую передачу. (Как вариант, можете представить, что владельцем буфера является сборщик мусора среды выполнения, а все методы — это просто объекты-получатели буфера.)
Properties
Gets a value indicating whether the current stream supports reading. |
|
Gets a value indicating whether the current stream supports seeking. |
|
Gets a value that determines whether the current stream can time out. (Inherited from Stream) |
|
Gets a value indicating whether the current stream supports writing. |
|
Gets or sets the number of bytes allocated for this stream. |
|
Gets the length of the stream in bytes. |
|
Gets or sets the current position within the stream. |
|
Gets or sets a value, in milliseconds, that determines how long the stream will attempt to read before timing out. (Inherited from Stream) |
|
Gets or sets a value, in milliseconds, that determines how long the stream will attempt to write before timing out. (Inherited from Stream) |
Конструкторы
Инициализирует новый экземпляр класса UnmanagedMemoryStream. |
|
Инициализирует новый экземпляр класса UnmanagedMemoryStream, используя заданное расположение и объем памяти. |
|
Инициализирует новый экземпляр класса UnmanagedMemoryStream, используя указанные значения расположения, объема памяти, общего объема памяти и доступа к файлам. |
|
Инициализирует новый экземпляр класса UnmanagedMemoryStream в безопасном буфере с указанным смещением и длиной. |
|
Инициализирует новый экземпляр класса UnmanagedMemoryStream в безопасном буфере с указанными смещением, длиной и правами доступа к файлам. |
Суть проблемы
В общем, проблема заключается в том, как выделяется память. Т.е если вы преаллоцируете память вы вряд-ли натолкнетесь на эти проблемы.
Итак, стандартный алгоритм работы: когда не хватает выделенного массива под стрим, выделяем новый блок в два раза больше, копируем туда данные из массива, забиваем на старый массив. Изначально это был неоптимальный алгоритм под векторы (но у нас-то стрим).
Во-первых, умножать массив на два чрезвычайно неоптимально для реальных обьемов.
Во-вторых, проблема заключается в том, что оверхед на стрим может достигать размера полезной информации. Это нормально для векторов с малым количеством элементов, но это чрезвычайно ужасно для стримов, которые могут достигать 10–100 мегабайт.
В-третьих, каждая реаллокация памяти приводит к тому, что у нас скапливается куча блоков памяти, которые не собираются GC, потому что он ленивый засранец. Для стрима в 130 мегабайт, к примеру, получается порядка 256 мегабайт мусорной памяти (это не учитывая лишние 126 мегабайт памяти, которую держит MemoryStream). В итоге рано или поздно к вам придёт пушистый OutOfMemoryException.