У меня есть StreamReader
объект, который я инициализировал с потоком, теперь я хочу сохранить этот поток на диск (поток может быть .gif
или .jpg
или или .pdf
).
Существующий код:
StreamReader sr = new StreamReader(myOtherObject.InputStream);
- Мне нужно сохранить это на диск (у меня есть имя файла).
- В будущем я могу захотеть сохранить это на SQL Server.
У меня также есть тип кодировки, который мне понадобится, если я сохраню его на SQL Server, правильно?
Ответы:
Как подчеркнул Tilendor в ответе Джона Скита, у потоков есть
CopyTo
метод начиная с .NET 4.Или с
using
синтаксисом:источник
myOtherObject.InputStream.Seek(0, SeekOrigin.Begin)
если вы еще не в начале или вы не будете копировать весь поток.Вы не должны использовать
StreamReader
для двоичных файлов (например, GIF-файлов или JPG).StreamReader
для текстовых данных. Вы почти наверняка потеряете данные, если будете использовать их для произвольных двоичных данных. (Если вы используете Encoding.GetEncoding (28591), вы, вероятно, будете в порядке, но какой в этом смысл?)Зачем вам вообще нужно использовать
StreamReader
? Почему бы просто не сохранить двоичные данные в виде двоичных данных и записать их обратно на диск (или в SQL) в виде двоичных данных?EDIT: Как это , кажется, что - то люди хотят видеть ... если вы действительно просто хотите скопировать один поток в другой (например , в файл) используйте что - то вроде этого:
Чтобы использовать его для выгрузки потока в файл, например:
Обратите внимание, что
Stream.CopyTo
был введен в .NET 4, служил в основном той же цели.источник
источник
stream
объект вusing(){}
скобки. Ваш метод не создал поток, поэтому он не должен избавляться от него.FileStream
вместо этого использовать, иначе он останется открытым, пока не будет собран мусор.File.WriteAllBytes(destinationFilePath, input.ToArray());
. В моем случае,input
этоMemoryStream
приходит изнутриZipArchive
.источник
File.WriteAllBytes(destinationFilePath, input.ToArray());
. В моем случае,input
этоMemoryStream
приходит изнутриZipArchive
.stream.Seek(0, SeekOrigin.Begin);
Я не получаю ответы на все вопросы
CopyTo
, где, возможно, системы, использующие приложение, возможно, не были обновлены до .NET 4.0+. Я знаю, что некоторые хотели бы заставить людей обновляться, но совместимость тоже хорошая.Во-вторых, я не использую поток для копирования из другого потока. Почему бы просто не сделать:
Получив байты, вы можете легко записать их в файл:
Этот код работает, поскольку я тестировал его с
.jpg
файлом, хотя я признаю, что использовал его только с небольшими файлами (менее 1 МБ). Один поток, без копирования между потоками, без кодирования, просто запишите байты! Не нужно слишком усложнять ситуацию,StreamReader
если у вас уже есть поток, который вы можете преобразоватьbytes
напрямую.ToArray()
!Единственный потенциальный недостаток, который я вижу в этом, заключается в том, что если у вас есть большой файл, то есть наличие его в виде потока и использование
.CopyTo()
или эквивалентное ему позволяетFileStream
потоковую передачу вместо использования байтового массива и чтения байтов один за другим. Это может быть медленнее делать это таким образом, в результате. Но он не должен задыхаться, поскольку.Write()
методFileStream
обрабатывает запись байтов, и он делает это только один байт за раз, поэтому он не будет засорять память, за исключением того, что у вас будет достаточно памяти, чтобы держать поток какbyte[]
объект . В моей ситуации, когда я использовал это, получаяOracleBlob
, я должен был перейти к abyte[]
, он был достаточно мал, и, кроме того, у меня не было никакого потока, так или иначе, поэтому я просто отправил свои байты в свою функцию выше.Другой вариант, использующий поток, состоит в том, чтобы использовать его с
CopyStream
функцией Джона Скита, которая была в другом посте - он просто использует,FileStream
чтобы взять входной поток и напрямую создать файл из него. Он не используетFile.Create
, как он (который изначально казался мне проблематичным, но позже обнаружил, что это скорее всего ошибка VS) ...источник
Close
из-заusing()
inputStream.Close()
, посмотрите еще раз -inputStream
отправляется как переменная.using
Находится наpath+filename
выходном потоке. Если вы говорилиfs.Close()
в серединеusing
, извините, вы были правы об этом, и я удалил это.источник
Почему бы не использовать объект FileStream?
источник
byte[]
, я думаю, что было бы редко, если бы вы передавали 1 ГБ + BLOB-объект в файл ... если у вас нет сайта, на котором есть DVD-потоки ... Плюс в любом случае, на большинстве компьютеров в настоящее время доступно как минимум 2 ГБ оперативной памяти. Caveat действителен, но я думаю, что это тот случай, когда он, вероятно, «достаточно хорош» для большинства задач.Другой вариант - получить поток
byte[]
и использоватьFile.WriteAllBytes
. Это должно сделать:Оборачивая его в метод расширения, вы получите лучшее именование:
источник
источник
FileStream
- приятно!Вот пример, который использует правильное использование и реализацию idisposable:
... а также есть это
Ключевым моментом является понимание правильного использования использования (которое должно быть реализовано при создании экземпляра объекта, который реализует идентификатор, как показано выше), и хорошее представление о том, как свойства работают для потоков. Позиция - это буквально индекс в потоке (который начинается с 0), за которым следует чтение каждого байта с использованием метода readbyte. В этом случае я, по сути, использую его вместо переменной цикла for и просто позволяю ему следовать по всему пути вплоть до длины, которая буквально является концом всего потока (в байтах). Игнорируйте в байтах, потому что это практически то же самое, и у вас будет что-то простое и элегантное, как это, которое решает все чисто.
Помните также, что метод ReadByte просто преобразует байт в процесс и может быть просто преобразован обратно.
Я добавлю еще одну реализацию, которую я недавно написал, чтобы создать динамический буфер, чтобы обеспечить последовательную запись данных для предотвращения массивной перегрузки.
Объяснение довольно простое: мы знаем, что нам нужно помнить весь набор данных, которые мы хотим записать, а также что мы хотим записывать только определенные суммы, поэтому мы хотим, чтобы первый цикл с последним параметром был пустым (так же, как и в то время, как ). Затем мы инициализируем буфер байтового массива, размер которого соответствует размеру переданного, и со вторым циклом мы сравниваем j с размером буфера и размером исходного, и если он больше, чем размер исходного байтовый массив, конец цикла.
источник