разница между потоком памяти и потоком файлов - PullRequest
49 голосов
/ 16 ноября 2011

Во время сериализации мы можем использовать либо поток памяти, либо поток файлов.

В чем основная разница между этими двумя?Что означает поток памяти?

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.Serialization.Formatters.Binary;

namespace Serilization
{
    class Program
    {
        static void Main(string[] args)
        {
            MemoryStream aStream = new MemoryStream();
            BinaryFormatter aBinaryFormat = new BinaryFormatter();
            aBinaryFormat.Serialize(aStream, person);
            aStream.Close();
        }
    }
}

Ответы [ 7 ]

74 голосов
/ 16 ноября 2011

Поток - это представление байтов. Оба эти класса являются производными от класса Stream, который является абстрактным по определению.

Как следует из названия, FileStream читает и пишет в файл, тогда как MemoryStream читает и пишет в память. Так что это относится к тому, где хранится поток.

Теперь все зависит от того, как вы планируете использовать оба из них. Например: предположим, что вы хотите читать двоичные данные из базы данных, вы должны использовать MemoryStream. Однако, если вы хотите прочитать файл в вашей системе, вы должны использовать FileStream.

Одним из быстрых преимуществ MemoryStream является то, что нет необходимости создавать временные буферы и файлы в приложении.

13 голосов
/ 22 октября 2018

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

Что такое поток?

Поток - это, по сути, поток данных между двумя местами, это скорее канал, а не содержимое этого канала.

Плохая аналогия для начала

Представьте себе опреснительную установку (которая забирает морскую воду, удаляет соль и выводит чистую питьевую воду в водопроводную сеть):

Опреснительная установка не может удалить соль со всего моря за один раз (и при этом мы не хотим, чтобы… где обитала морская рыба?), Поэтому вместо этого мы имеем:

  • A SeaStream, который всасывает определенное количество воды за раз в растение.
  • То, что SeaStream связано с DesalinationStream для удаления соли
  • А выход DesalinationStream подключен к DrinkingWaterNetworkStream для подачи теперь бессолевой воды в систему питьевого водоснабжения.

ОК, так какое отношение это имеет к компьютерам?

Перемещение больших файлов одновременно может быть проблематичным

Часто в вычислениях мы хотим перемещать данные между двумя точками, например, с внешнего жесткого диска на двоичное поле в базе данных (чтобы использовать пример, приведенный в другом ответе). Мы можем сделать это, скопировав все данные из файла из местоположения A в память компьютера и оттуда в местоположение B, но если файл большой или источник или место назначения потенциально ненадежны, то перемещение всего файла за один раз может быть невыполнимым или неразумным.

Например, скажем, мы хотим переместить большой файл на USB-накопителе в поле в базе данных. Мы могли бы использовать объект System.IO.File для извлечения всего этого файла в память компьютера, а затем использовать соединение с базой данных для передачи этого файла в базу данных.

Но это потенциально проблематично, что, если файл больше, чем доступная оперативная память компьютера? Теперь файл потенциально будет кэшироваться на жесткий диск, что является медленным, и это может даже замедлить работу компьютера.

Аналогично, что если источник данных ненадежен, например, копирование файла с сетевого диска при медленном и нестабильном соединении WiFi? Попытка скопировать большой файл за один раз может приводить в бешенство, потому что вы получаете половину файла, а затем соединение разрывается, и вам приходится начинать все сначала, только для того, чтобы он потенциально мог снова выйти из строя.

Может быть лучше разбить файл и переместить его по частям за раз

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

  • Мы можем использовать FileStream для извлечения данных из файла по частям за один раз
  • и API базы данных может сделать доступной конечную точку MemoryStream, которую мы можем записать в кусок за раз.
  • Мы соединяем эти два «канала» вместе, чтобы передавать кусочки файла из файла в базу данных.

Даже если файл не был слишком большим для хранения в оперативной памяти, без потоков мы все равно выполняли операции с числами или операции чтения / записи, которые нам не нужны. Этапы, которые мы проводим, были:

  1. Извлечение данных с диска (медленно)
  2. Запись в объект File в памяти компьютера (немного быстрее)
  3. Чтение из этого объекта File в памяти компьютера (снова быстрее)
  4. Запись в базу данных (вероятно, медленная, поскольку в конце этого канала, возможно, есть вращающийся жесткий диск)

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

Другие преимущества потоков

Отделение извлечения данных от записи данных также позволяет нам выполнять действия между извлечением данных и их передачей.Например, мы могли бы добавить этап шифрования или записать входящие данные в более чем один тип выходного потока (например, в FileStream и NetworkStream).

Потоки также позволяют нам писать код там, где мыможет возобновить операцию, если передача не пройдена частично.Отслеживая количество фрагментов, которые мы переместили, если передача не удалась (например, если сетевое соединение прерывается), мы можем перезапустить поток с того места, в котором мы получили последний фрагмент (это offset вBeginRead метод).

8 голосов
/ 16 ноября 2011

В простейшей форме MemoryStream записывает данные в память, а FileStream записывает данные в файл.

Как правило, я использую MemoryStream, если мне нужен поток, но я не хочу, чтобы что-либо ударилодиск, и я использую FileStream при записи файла на диск.

6 голосов
/ 16 ноября 2011

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

5 голосов
/ 09 августа 2012

Имея горький опыт по этому вопросу, вот что я узнал.если требуется производительность, вы должны скопировать содержимое файлового потока в поток памяти.Мне пришлось обработать содержимое 144 файлов по 528 Кбайт каждый и представить результат пользователю.Это заняло 250 секунд.(!!!!).Когда я просто скопировал содержимое каждого файлового потока в поток памяти (метод CopyTo), ничего не меняя, время упало примерно до 32 секунд.Обратите внимание, что каждый раз, когда вы копируете один поток в другой, поток добавляется в конец целевого потока, поэтому вам может понадобиться «перемотать» его перед копированием в него.Надеюсь, поможет.

2 голосов
/ 16 ноября 2011

Поток памяти обрабатывает данные через буфер в памяти.Файловый поток имеет дело с файлами на диске.

0 голосов
/ 05 октября 2013

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

Итак, в большинстве случаев вы хотите сериализовать на диск, поэтому вы используете Filestream для сериализации.

...