Разница между загрузкой файла по пути и из потока С#

Это дополнительный вопрос к этому вопросу:

Разница между путем к файлу и файловым потоком?

Я не полностью понял все ответы в связанном вопросе.

Я использую метод Microsoft.SqlServer.Dac.BacPackage, который содержит метод Load с двумя перегрузками: один получает строковый путь, а другой — Stream.

Это документация метода Load:

https://docs.microsoft.com/en-us/dotnet/api/microsoft.sqlserver.dac.bacpackage.load?view=sql-dacfx-150

В чем именно разница между ними? Правильно ли я предполагаю, что перегрузка строкового пути сначала сохраняет весь файл в памяти, а поток - нет? Есть ли другие отличия?


person Yonatan Nir    schedule 21.02.2021    source источник
comment
Перегрузка строкового пути к файлу, скорее всего, просто открывает файловый поток, а затем передает его перегрузке Stream. Если у вас уже есть FileStream или, возможно, MemoryStream, содержащий Dac, вы должны использовать перегрузку Stream, но если все, что у вас есть, это имя файла и вы не хотите самостоятельно управлять FileStream, вы должны использовать перегрузку строки. Сомнительно, что кроме этого есть какая-то разница   -  person pinkfloydx33    schedule 21.02.2021
comment
Я думаю, вам следует прочитать что такое поток. В настоящее время вы спрашиваете, как реализованы два разных метода, и вам нужно посмотреть исходный код, чтобы понять. Что именно вас в этом интересует?   -  person Xerillio    schedule 21.02.2021
comment
Вы можете обратиться к этому social.msdn.microsoft.com/Forums/vstudio/en-US/   -  person vivek nuna    schedule 21.02.2021
comment
@Xerillio Это то, что я писал о загрузке бакпака. У меня могут быть какие-то огромные бакпаки, которые я хочу загрузить, и я не хочу, чтобы они загружались в память целиком, а чтобы они загружались в потоке   -  person Yonatan Nir    schedule 21.02.2021
comment
@YonatanNir В этом случае только создатели Microsoft.SqlServer.Dac смогут ответить на ваш вопрос или, если вы сможете найти исходный код, вы можете проверить его там. Все остальные смогут лишь дать квалифицированное предположение. По этой причине я не думаю, что этот вопрос относится к SO.   -  person Xerillio    schedule 21.02.2021


Ответы (2)


Нет, файл обычно не загружается полностью сразу.

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

Параметр Stream означает, что вы открываете файл и передаете результат Stream. Вы также можете передать любой другой тип Stream, такой как сетевой поток, zip-поток или поток дешифрования, поток с поддержкой памяти, что угодно.

person Charlieface    schedule 21.02.2021
comment
Как я могу проверить, действительно ли то, что вы сказали о перегрузке строки, имеет место? - person Yonatan Nir; 21.02.2021
comment
Я не вижу причин полагать, что это будет чем-то отличаться от, вероятно, сотен других таких пар функций в .NET, это довольно стандартно. Вам нужно будет увидеть исходный код, чтобы быть уверенным, я не могу найти его на Github, поэтому попробуйте декомпилировать его самостоятельно. - person Charlieface; 21.02.2021
comment
Скажем так, значит ли это, что файл bacpac НЕ загружается полностью в память? - person Yonatan Nir; 21.02.2021
comment
Правильно, он будет загружаться по крупицам. Может случиться так, что когда он будет завершен, все это будет обработано и загружено в объекты (в зависимости от того, что на самом деле должна делать функция), но фактические байты файла как целого блоба не присутствуют в памяти все сразу, так что это определенно не требует памяти, вдвое превышающей размер файла. - person Charlieface; 21.02.2021

Короткий ответ:

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

Подробный ответ

Вы можете рассматривать поток как последовательность байтов. Причина использования потока вместо byte[] или List<byte> заключается в том, что если последовательность очень, очень большая, и вам не нужен доступ ко всем байтам одновременно, было бы напрасно помещать все байты в памяти до их обработки.

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

Вот почему люди хотят читать файл как поток.

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

using (Stream fileStream = File.Open(fileName)
{
    ProcessInputData(fileStream);
}

Or:

byte[] bytesToProcess = ...
using (Stream memoryStream = new MemoryStream(bytesToProcess))
{
    ProcessInputData(memoryStream);
}

Or:

string operatorInput = this.textBox1.Text;
using (Stream memoryStream = new MemoryStream(operatorInput))
{
    ProcessInputData(memoryStream);
}

Заключение

Методы используют потоки в своем интерфейсе, чтобы указать, что им не нужны все данные в памяти сразу. Достаточно одного или каждого куска. Вызывающий может решать, откуда берутся данные.

person Harald Coppoolse    schedule 12.04.2021