Mam StreamReader
obiekt, który zainicjowałem ze strumieniem, teraz chcę zapisać ten strumień na dysku (strumień może być .gif
lub .jpg
lub .pdf
).
Istniejący kod:
StreamReader sr = new StreamReader(myOtherObject.InputStream);
- Muszę zapisać to na dysku (mam nazwę pliku).
- W przyszłości mogę chcieć zapisać to na SQL Server.
Mam również typ kodowania, który będzie potrzebny, jeśli będę go przechowywać na serwerze SQL, prawda?
Odpowiedzi:
Jak podkreśla Tilendor w odpowiedzi Jona Skeeta, strumienie mają
CopyTo
metodę od .NET 4.Lub ze
using
składnią:źródło
myOtherObject.InputStream.Seek(0, SeekOrigin.Begin)
jeśli jeszcze nie jesteś na początku lub nie skopiujesz całego strumienia.ty wolno używać
StreamReader
do plików binarnych (takich jak gif lub jpg).StreamReader
dotyczy danych tekstowych . Prawie na pewno stracisz dane, jeśli użyjesz ich do dowolnych danych binarnych. (Jeśli użyjesz Encoding.GetEncoding (28591) prawdopodobnie będziesz w porządku, ale o co chodzi?)Dlaczego w ogóle potrzebujesz
StreamReader
? Dlaczego nie po prostu zachować dane binarne jako dane binarne i zapisać je z powrotem na dysk (lub SQL) jako dane binarne?EDIT: Jak to wydaje się być coś ludzie chcą zobaczyć ... jeśli nie po prostu chcesz skopiować jednego strumienia do drugiego (np do pliku) używać coś takiego:
Aby użyć go do zrzucenia strumienia do pliku, na przykład:
Zauważ, że
Stream.CopyTo
został wprowadzony w .NET 4, służąc w zasadzie do tego samego celu.źródło
źródło
stream
obiektu wusing(){}
nawiasie. Twoja metoda nie utworzyła strumienia, więc nie należy go wyrzucać.FileStream
zamiast tego użyć, w przeciwnym razie będzie on otwarty, dopóki nie zostanie wyrzucony śmieci.File.WriteAllBytes(destinationFilePath, input.ToArray());
. W moim przypadku,input
jestMemoryStream
przyjście z obrębuZipArchive
.źródło
File.WriteAllBytes(destinationFilePath, input.ToArray());
. W moim przypadku,input
jestMemoryStream
przyjście z obrębuZipArchive
.stream.Seek(0, SeekOrigin.Begin);
Nie otrzymuję wszystkich odpowiedzi
CopyTo
, a być może systemy korzystające z aplikacji mogły nie zostać zaktualizowane do wersji .NET 4.0+. Wiem, że niektórzy chcieliby zmusić ludzi do aktualizacji, ale kompatybilność też jest dobra.Inna sprawa, że nie używam strumienia do kopiowania z innego strumienia. Dlaczego nie tylko:
Gdy masz bajty, możesz łatwo zapisać je w pliku:
Ten kod działa tak, jak przetestowałem go z
.jpg
plikiem, choć przyznaję, że użyłem go tylko z małymi plikami (mniej niż 1 MB). Jeden strumień, bez kopiowania między strumieniami, niepotrzebne kodowanie, wystarczy napisać bajty! Nie musisz nadmiernie komplikować rzeczy,StreamReader
jeśli masz już strumień, na który możnabytes
bezpośrednio przekonwertować.ToArray()
!Jedyne potencjalne wady, które widzę podczas robienia tego w ten sposób, to to, że masz duży plik, mając go jako strumień, a użycie
.CopyTo()
lub odpowiednik pozwalaFileStream
na przesyłanie strumieniowe zamiast korzystania z tablicy bajtów i odczytywania bajtów jeden po drugim. W rezultacie może być wolniej. Ale nie powinien się dusić, ponieważ.Write()
metodaFileStream
uchwytów zapisujących bajty, i robi to tylko jeden bajt na raz, więc nie zapycha pamięci, z wyjątkiem tego, że będziesz musiał mieć wystarczającą ilość pamięci, aby utrzymać strumień jakobyte[]
przedmiot . W mojej sytuacji, w której korzystałem z tego,OracleBlob
musiałem iść dobyte[]
, był wystarczająco mały, a poza tym i tak nie było dla mnie żadnego streamingu, więc po prostu wysłałem moje bajty do mojej funkcji powyżej.Inną opcją, wykorzystującą strumień, byłoby użycie go z
CopyStream
funkcją Jona Skeeta, która była w innym poście - służy to tylkoFileStream
do pobrania strumienia wejściowego i utworzenia z niego bezpośrednio pliku. Nie działaFile.Create
, tak jak on (co początkowo wydawało mi się problematyczne, ale później stwierdził, że to prawdopodobnie tylko błąd VS ...).źródło
Close
powoduusing()
inputStream.Close()
, spójrz ponownie -inputStream
jest wysyłany jako zmienna.using
Jest wpath+filename
strumieniu wyjściowym. Jeśli mówiłeś o tymfs.Close()
w środkuusing
, przepraszam, miałeś rację, a ja to usunąłem.źródło
Dlaczego nie użyć obiektu FileStream?
źródło
byte[]
, myślę, że rzadkie byłoby przesyłanie strumieniowe pliku 1 GB + BLOB do pliku ... chyba że masz witrynę, która przechowuje torrenty DVD ... Plus , większość komputerów ma obecnie przynajmniej 2 GB pamięci RAM… Zastrzeżenie jest ważne, ale myślę, że jest to przypadek, w którym prawdopodobnie jest „wystarczająco dobry” do większości zadań.Inną opcją jest doprowadzenie strumienia do
byte[]
i użycieFile.WriteAllBytes
. To powinno zrobić:Zawijanie go w metodzie rozszerzenia daje lepszą nazwę:
źródło
źródło
FileStream
- fajnie!Oto przykład, który wykorzystuje odpowiednie zastosowania i implementację idisposable:
... i jest też to
Kluczem jest zrozumienie prawidłowego użycia use (które powinno zostać zaimplementowane przy tworzeniu instancji obiektu, który implementuje idisposable, jak pokazano powyżej) oraz dobre wyobrażenie o tym, jak właściwości działają dla strumieni. Pozycja jest dosłownie indeksem w strumieniu (który zaczyna się od 0), po którym następuje odczyt każdego bajtu przy użyciu metody readbyte. W tym przypadku zasadniczo używam go zamiast zmiennej pętli for i po prostu pozwalam mu przejść przez całą długość aż do długości, która jest LITERALNIE końcem całego strumienia (w bajtach). Ignoruj w bajtach, ponieważ jest praktycznie taki sam, a będziesz mieć coś prostego i eleganckiego, takiego jak ten, który wszystko rozwiąże.
Należy również pamiętać, że metoda ReadByte po prostu rzutuje bajt na liczbę całkowitą w procesie i można go po prostu przekonwertować.
Dodam kolejną implementację, którą niedawno napisałem, aby utworzyć rodzaj dynamicznego bufora, aby zapewnić sekwencyjne zapisywanie danych, aby zapobiec ogromnemu przeciążeniu
Wyjaśnienie jest dość proste: wiemy, że musimy pamiętać o całym zestawie danych, które chcemy zapisać, a także, że chcemy zapisywać tylko określone ilości, więc chcemy, aby pierwsza pętla z ostatnim parametrem była pusta (tak jak podczas gdy ). Następnie inicjalizujemy bufor tablicy bajtów, który jest ustawiony na rozmiar tego, co zostało przekazane, a za pomocą drugiej pętli porównujemy j z rozmiarem bufora i rozmiarem oryginalnego, a jeśli jest większy niż rozmiar oryginału tablica bajtów, zakończ bieg.
źródło